qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

matrix.c (7490B)


      1 /*
      2 Copyright 2011 Jun Wako <wakojun@gmail.com>
      3 
      4 This program is free software: you can redistribute it and/or modify
      5 it under the terms of the GNU General Public License as published by
      6 the Free Software Foundation, either version 2 of the License, or
      7 (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 GNU General Public License for more details.
     13 
     14 You should have received a copy of the GNU General Public License
     15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16 
     17 Ported to QMK by Peter Roe <pete@13bit.me>
     18 */
     19 
     20 #include <stdint.h>
     21 #include <stdbool.h>
     22 #include <avr/io.h>
     23 #include <util/delay.h>
     24 #include "print.h"
     25 #include "util.h"
     26 #include "debug.h"
     27 #include "adb.h"
     28 #include "matrix.h"
     29 #include "report.h"
     30 #include "host.h"
     31 #include "led.h"
     32 #include "timer.h"
     33 
     34 #ifndef ADB_MOUSE_MAXACC
     35 #    define ADB_MOUSE_MAXACC 8
     36 #endif
     37 
     38 static bool is_iso_layout = false;
     39 
     40 // matrix state buffer(1:on, 0:off)
     41 static matrix_row_t matrix[MATRIX_ROWS];
     42 
     43 static void register_key(uint8_t key);
     44 
     45 __attribute__ ((weak))
     46 void matrix_init_kb(void) {
     47     matrix_init_user();
     48 }
     49 
     50 __attribute__ ((weak))
     51 void matrix_scan_kb(void) {
     52     matrix_scan_user();
     53 }
     54 
     55 __attribute__ ((weak))
     56 void matrix_init_user(void) {
     57 }
     58 
     59 __attribute__ ((weak))
     60 void matrix_scan_user(void) {
     61 }
     62 
     63 void matrix_init(void)
     64 {
     65     adb_host_init();
     66 
     67     // wait for keyboard to boot up and receive command
     68     _delay_ms(2000);
     69 
     70     // initialize matrix state: all keys off
     71     for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
     72 
     73     // debug_enable = true;
     74     // debug_matrix = true;
     75     // debug_keyboard = true;
     76     // debug_mouse = true;
     77     // print("debug enabled.\n");
     78 
     79     matrix_init_kb();
     80 }
     81 
     82 #ifdef ADB_MOUSE_ENABLE
     83 
     84 #ifdef MAX
     85 #undef MAX
     86 #endif
     87 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
     88 
     89 static report_mouse_t mouse_report = {};
     90 
     91 void housekeeping_task_kb(void) {
     92     adb_mouse_task();
     93 }
     94 
     95 void adb_mouse_task(void)
     96 {
     97     uint16_t codes;
     98     int16_t x, y;
     99     static int8_t mouseacc;
    100 
    101     /* tick of last polling */
    102     static uint16_t tick_ms;
    103 
    104     // polling with 12ms interval
    105     if (timer_elapsed(tick_ms) < 12) return;
    106     tick_ms = timer_read();
    107 
    108     codes = adb_host_mouse_recv();
    109     // If nothing received reset mouse acceleration, and quit.
    110     if (!codes) {
    111         mouseacc = 1;
    112         return;
    113     };
    114     // Bit sixteen is button.
    115     if (~codes & (1 << 15))
    116         mouse_report.buttons |= MOUSE_BTN1;
    117     if (codes & (1 << 15))
    118         mouse_report.buttons &= ~MOUSE_BTN1;
    119     // lower seven bits are movement, as signed int_7.
    120     // low byte is X-axis, high byte is Y.
    121     y = (codes>>8 & 0x3F);
    122     x = (codes>>0 & 0x3F);
    123     // bit seven and fifteen is negative
    124     // usb does not use int_8, but int_7 (measuring distance) with sign-bit.
    125     if (codes & (1 << 6))
    126           x = (x-0x40);
    127     if (codes & (1 << 14))
    128          y = (y-0x40);
    129     // Accelerate mouse. (They weren't meant to be used on screens larger than 320x200).
    130     x *= mouseacc;
    131     y *= mouseacc;
    132     // Cap our two bytes per axis to one byte.
    133     // Easier with a MIN-function, but since -MAX(-a,-b) = MIN(a,b)...
    134 	 // I.E. MIN(MAX(x,-127),127) = -MAX(-MAX(x, -127), -127) = MIN(-MIN(-x,127),127)
    135     mouse_report.x = -MAX(-MAX(x, -127), -127);
    136     mouse_report.y = -MAX(-MAX(y, -127), -127);
    137     if (debug_mouse) {
    138             print("adb_host_mouse_recv: "); print_bin16(codes); print("\n");
    139             print("adb_mouse raw: [");
    140             print_hex8(mouseacc); print(" ");
    141             print_hex8(mouse_report.buttons); print("|");
    142             print_decs(mouse_report.x); print(" ");
    143             print_decs(mouse_report.y); print("]\n");
    144     }
    145     // Send result by usb.
    146     host_mouse_send(&mouse_report);
    147     // increase acceleration of mouse
    148     mouseacc += ( mouseacc < ADB_MOUSE_MAXACC ? 1 : 0 );
    149     return;
    150 }
    151 #endif
    152 
    153 uint8_t matrix_scan(void)
    154 {
    155     /* extra_key is volatile and more convoluted than necessary because gcc refused
    156     to generate valid code otherwise. Making extra_key uint8_t and constructing codes
    157     here via codes = extra_key<<8 | 0xFF; would consistently fail to even LOAD
    158     extra_key from memory, and leave garbage in the high byte of codes. I tried
    159     dozens of code variations and it kept generating broken assembly output. So
    160     beware if attempting to make extra_key code more logical and efficient. */
    161     static volatile uint16_t extra_key = 0xFFFF;
    162     uint16_t codes;
    163     uint8_t key0, key1;
    164 
    165     /* tick of last polling */
    166     static uint16_t tick_ms;
    167 
    168     codes = extra_key;
    169     extra_key = 0xFFFF;
    170 
    171     if ( codes == 0xFFFF )
    172     {
    173         // polling with 12ms interval
    174         if (timer_elapsed(tick_ms) < 12) return 0;
    175         tick_ms = timer_read();
    176 
    177         codes = adb_host_kbd_recv();
    178     }
    179 
    180     key0 = codes>>8;
    181     key1 = codes&0xFF;
    182 
    183     if (debug_matrix && codes) {
    184         print("adb_host_kbd_recv: "); print_hex16(codes); print("\n");
    185     }
    186 
    187     if (codes == 0) {                           // no keys
    188         return 0;
    189     } else if (codes == 0x7F7F) {   // power key press
    190         register_key(0x7F);
    191     } else if (codes == 0xFFFF) {   // power key release
    192         register_key(0xFF);
    193     } else if (key0 == 0xFF) {      // error
    194         xprintf("adb_host_kbd_recv: ERROR(%d)\n", codes);
    195         // something wrong or plug-in
    196         matrix_init();
    197         return key1;
    198     } else {
    199         /* Swap codes for ISO keyboard
    200          * https://github.com/tmk/tmk_keyboard/issues/35
    201          *
    202          * ANSI
    203          * ,-----------    ----------.
    204          * | *a|  1|  2     =|Backspa|
    205          * |-----------    ----------|
    206          * |Tab  |  Q|     |  ]|   *c|
    207          * |-----------    ----------|
    208          * |CapsLo|  A|    '|Return  |
    209          * |-----------    ----------|
    210          * |Shift   |      Shift     |
    211          * `-----------    ----------'
    212          *
    213          * ISO
    214          * ,-----------    ----------.
    215          * | *a|  1|  2     =|Backspa|
    216          * |-----------    ----------|
    217          * |Tab  |  Q|     |  ]|Retur|
    218          * |-----------    -----`    |
    219          * |CapsLo|  A|    '| *c|    |
    220          * |-----------    ----------|
    221          * |Shif| *b|      Shift     |
    222          * `-----------    ----------'
    223          *
    224          *         ADB scan code   USB usage
    225          *         -------------   ---------
    226          * Key     ANSI    ISO     ANSI    ISO
    227          * ---------------------------------------------
    228          * *a      0x32    0x0A    0x35    0x35
    229          * *b      ----    0x32    ----    0x64
    230          * *c      0x2A    0x2A    0x31    0x31(or 0x32)
    231          */
    232         if (is_iso_layout) {
    233             if ((key0 & 0x7F) == 0x32) {
    234                 key0 = (key0 & 0x80) | 0x0A;
    235             } else if ((key0 & 0x7F) == 0x0A) {
    236                 key0 = (key0 & 0x80) | 0x32;
    237             }
    238         }
    239         register_key(key0);
    240         if (key1 != 0xFF)       // key1 is 0xFF when no second key.
    241             extra_key = key1<<8 | 0xFF; // process in a separate call
    242     }
    243 
    244     matrix_scan_kb();
    245     return 1;
    246 }
    247 
    248 void matrix_print(void){
    249 
    250 }
    251 
    252 inline
    253 matrix_row_t matrix_get_row(uint8_t row)
    254 {
    255     return matrix[row];
    256 }
    257 
    258 inline
    259 static void register_key(uint8_t key)
    260 {
    261     uint8_t col, row;
    262     col = key&0x07;
    263     row = (key>>3)&0x0F;
    264     if (key&0x80) {
    265         matrix[row] &= ~(1<<col);
    266     } else {
    267         matrix[row] |=  (1<<col);
    268     }
    269 }