/* Copyright 2011 Jun Wako 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 . */ /* * scan matrix */ #include #include #include #include "print.h" #include "debug.h" #include "util.h" #include "timer.h" #include "matrix.h" #include "hhkb_avr.h" #include #include "suspend.h" #include "lufa.h" // matrix power saving #define MATRIX_POWER_SAVE 10000 static uint32_t matrix_last_modified = 0; // matrix state buffer(1:on, 0:off) static matrix_row_t *matrix; static matrix_row_t *matrix_prev; static matrix_row_t _matrix0[MATRIX_ROWS]; static matrix_row_t _matrix1[MATRIX_ROWS]; inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } inline uint8_t matrix_cols(void) { return MATRIX_COLS; } void matrix_init(void) { #ifdef DEBUG debug_enable = true; debug_keyboard = true; #endif KEY_INIT(); // initialize matrix state: all keys off for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00; matrix = _matrix0; matrix_prev = _matrix1; } uint8_t matrix_scan(void) { uint8_t *tmp; tmp = matrix_prev; matrix_prev = matrix; matrix = tmp; // power on if (!KEY_POWER_STATE()) KEY_POWER_ON(); for (uint8_t row = 0; row < MATRIX_ROWS; row++) { for (uint8_t col = 0; col < MATRIX_COLS; col++) { KEY_SELECT(row, col); _delay_us(5); // Not sure this is needed. This just emulates HHKB controller's behaviour. if (matrix_prev[row] & (1< 20/(1000000/TIMER_RAW_FREQ)) { matrix[row] = matrix_prev[row]; } _delay_us(5); KEY_PREV_OFF(); KEY_UNABLE(); // NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE. // This takes 25us or more to make sure KEY_STATE returns to idle state. _delay_us(75); } if (matrix[row] ^ matrix_prev[row]) matrix_last_modified = timer_read32(); } // power off if (KEY_POWER_STATE() && (USB_DeviceState == DEVICE_STATE_Suspended || USB_DeviceState == DEVICE_STATE_Unattached ) && timer_elapsed32(matrix_last_modified) > MATRIX_POWER_SAVE) { KEY_POWER_OFF(); suspend_power_down(); } return 1; } bool matrix_is_modified(void) { for (uint8_t i = 0; i < MATRIX_ROWS; i++) { if (matrix[i] != matrix_prev[i]) return true; } return false; } inline bool matrix_has_ghost(void) { return false; } inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & (1<