matrix.c (2761B)
1 /* Copyright 2018 James Laird-Wah 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 #include "matrix.h" 17 #include "i2c_master.h" 18 #include <string.h> 19 #include "model01.h" 20 21 /* If no key events have occurred, the scanners will time out on reads. 22 * So we don't want to be too permissive here. */ 23 #define I2C_TIMEOUT 10 24 25 static matrix_row_t rows[MATRIX_ROWS]; 26 #define ROWS_PER_HAND (MATRIX_ROWS / 2) 27 28 // user-defined overridable functions 29 30 __attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } 31 32 __attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } 33 34 __attribute__((weak)) void matrix_init_user(void) {} 35 36 __attribute__((weak)) void matrix_scan_user(void) {} 37 38 // helper functions 39 inline 40 uint8_t matrix_rows(void) { 41 return MATRIX_ROWS; 42 } 43 44 inline 45 uint8_t matrix_cols(void) { 46 return MATRIX_COLS; 47 } 48 49 static int i2c_read_hand(int hand) { 50 uint8_t buf[5]; 51 i2c_status_t ret = i2c_receive(I2C_ADDR(hand), buf, sizeof(buf), I2C_TIMEOUT); 52 if (ret != I2C_STATUS_SUCCESS) 53 return 1; 54 55 if (buf[0] != TWI_REPLY_KEYDATA) 56 return 2; 57 58 int start_row = hand ? ROWS_PER_HAND : 0; 59 uint8_t *out = &rows[start_row]; 60 memcpy(out, &buf[1], 4); 61 return 0; 62 } 63 64 static int i2c_set_keyscan_interval(int hand, int delay) { 65 uint8_t buf[] = {TWI_CMD_KEYSCAN_INTERVAL, delay}; 66 i2c_status_t ret = i2c_transmit(I2C_ADDR(hand), buf, sizeof(buf), I2C_TIMEOUT); 67 return ret; 68 } 69 70 void matrix_init(void) { 71 /* Ensure scanner power is on - else right hand will not work */ 72 gpio_set_pin_output(C7); 73 gpio_write_pin_high(C7); 74 75 i2c_init(); 76 i2c_set_keyscan_interval(LEFT, 2); 77 i2c_set_keyscan_interval(RIGHT, 2); 78 memset(rows, 0, sizeof(rows)); 79 80 matrix_init_kb(); 81 } 82 83 uint8_t matrix_scan(void) { 84 uint8_t ret = 0; 85 ret |= i2c_read_hand(LEFT); 86 ret |= i2c_read_hand(RIGHT); 87 matrix_scan_kb(); 88 return ret; 89 } 90 91 inline 92 matrix_row_t matrix_get_row(uint8_t row) { 93 return rows[row]; 94 } 95 96 void matrix_print(void) { 97 print("\nr/c 0123456789ABCDEF\n"); 98 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 99 print_hex8(row); print(": "); 100 print_bin_reverse16(matrix_get_row(row)); 101 print("\n"); 102 } 103 } 104 105 /* vim: set ts=2 sw=2 et: */