195 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * scan matrix
 | |
|  */
 | |
| #include <stdint.h>
 | |
| #include <stdbool.h>
 | |
| #include <avr/io.h>
 | |
| #include <util/delay.h>
 | |
| #include "print.h"
 | |
| #include "util.h"
 | |
| #include "debug.h"
 | |
| #include "adb.h"
 | |
| #include "matrix_skel.h"
 | |
| 
 | |
| 
 | |
| #if (MATRIX_COLS > 16)
 | |
| #   error "MATRIX_COLS must not exceed 16"
 | |
| #endif
 | |
| #if (MATRIX_ROWS > 255)
 | |
| #   error "MATRIX_ROWS must not exceed 255"
 | |
| #endif
 | |
| 
 | |
| 
 | |
| static bool _matrix_is_modified = false;
 | |
| 
 | |
| // matrix state buffer(1:on, 0:off)
 | |
| #if (MATRIX_COLS <= 8)
 | |
| static uint8_t *matrix;
 | |
| static uint8_t _matrix0[MATRIX_ROWS];
 | |
| #else
 | |
| static uint16_t *matrix;
 | |
| static uint16_t _matrix0[MATRIX_ROWS];
 | |
| #endif
 | |
| 
 | |
| #ifdef MATRIX_HAS_GHOST
 | |
| static bool matrix_has_ghost_in_row(uint8_t row);
 | |
| #endif
 | |
| static void _register_key(uint8_t key);
 | |
| 
 | |
| 
 | |
| inline
 | |
| uint8_t matrix_rows(void)
 | |
| {
 | |
|     return MATRIX_ROWS;
 | |
| }
 | |
| 
 | |
| inline
 | |
| uint8_t matrix_cols(void)
 | |
| {
 | |
|     return MATRIX_COLS;
 | |
| }
 | |
| 
 | |
| void matrix_init(void)
 | |
| {
 | |
|     adb_host_init();
 | |
| 
 | |
|     // initialize matrix state: all keys off
 | |
|     for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
 | |
|     matrix = _matrix0;
 | |
| 
 | |
|     print_enable = true;
 | |
|     debug_enable = true;
 | |
|     debug_matrix = true;
 | |
|     debug_keyboard = true;
 | |
|     debug_mouse = true;
 | |
|     print("debug enabled.\n");
 | |
|     return;
 | |
| }
 | |
| 
 | |
| uint8_t matrix_scan(void)
 | |
| {
 | |
|     uint16_t codes;
 | |
|     uint8_t key0, key1;
 | |
| 
 | |
|     _matrix_is_modified = false;
 | |
| 
 | |
|     codes = adb_host_kbd_recv();
 | |
|     key0 = codes>>8;
 | |
|     key1 = codes&0xFF;
 | |
|     if (debug_matrix) {
 | |
|         //print("adb_host_kbd_recv: "); phex16(codes); print("\n");
 | |
|     }
 | |
| 
 | |
|     if (codes == 0) {                           // no keys
 | |
|         return 0;
 | |
|     } else if (key0 == 0xFF && key1 != 0xFF) {  // error
 | |
|         return codes&0xFF;
 | |
|     } else {
 | |
|         _matrix_is_modified = true;
 | |
|         _register_key(key0);
 | |
|         if (key1 != 0xFF)       // key1 is 0xFF when no second key.
 | |
|             _register_key(key1);
 | |
|     }
 | |
| 
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| bool matrix_is_modified(void)
 | |
| {
 | |
|     return _matrix_is_modified;
 | |
| }
 | |
| 
 | |
| inline
 | |
| bool matrix_has_ghost(void)
 | |
| {
 | |
| #ifdef MATRIX_HAS_GHOST
 | |
|     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
 | |
|         if (matrix_has_ghost_in_row(i))
 | |
|             return true;
 | |
|     }
 | |
| #endif
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| inline
 | |
| bool matrix_is_on(uint8_t row, uint8_t col)
 | |
| {
 | |
|     return (matrix[row] & (1<<col));
 | |
| }
 | |
| 
 | |
| inline
 | |
| #if (MATRIX_COLS <= 8)
 | |
| uint8_t matrix_get_row(uint8_t row)
 | |
| #else
 | |
| uint16_t matrix_get_row(uint8_t row)
 | |
| #endif
 | |
| {
 | |
|     return matrix[row];
 | |
| }
 | |
| 
 | |
| void matrix_print(void)
 | |
| {
 | |
| #if (MATRIX_COLS <= 8)
 | |
|     print("\nr/c 01234567\n");
 | |
| #else
 | |
|     print("\nr/c 0123456789ABCDEF\n");
 | |
| #endif
 | |
|     for (uint8_t row = 0; row < matrix_rows(); row++) {
 | |
|         phex(row); print(": ");
 | |
| #if (MATRIX_COLS <= 8)
 | |
|         pbin_reverse(matrix_get_row(row));
 | |
| #else
 | |
|         pbin_reverse16(matrix_get_row(row));
 | |
| #endif
 | |
| #ifdef MATRIX_HAS_GHOST
 | |
|         if (matrix_has_ghost_in_row(row)) {
 | |
|             print(" <ghost");
 | |
|         }
 | |
| #endif
 | |
|         print("\n");
 | |
|     }
 | |
| }
 | |
| 
 | |
| uint8_t matrix_key_count(void)
 | |
| {
 | |
|     uint8_t count = 0;
 | |
|     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
 | |
| #if (MATRIX_COLS <= 8)
 | |
|         count += bitpop(matrix[i]);
 | |
| #else
 | |
|         count += bitpop16(matrix[i]);
 | |
| #endif
 | |
|     }
 | |
|     return count;
 | |
| }
 | |
| 
 | |
| #ifdef MATRIX_HAS_GHOST
 | |
| inline
 | |
| static bool matrix_has_ghost_in_row(uint8_t row)
 | |
| {
 | |
|     // no ghost exists in case less than 2 keys on
 | |
|     if (((matrix[row] - 1) & matrix[row]) == 0)
 | |
|         return false;
 | |
| 
 | |
|     // ghost exists in case same state as other row
 | |
|     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
 | |
|         if (i != row && (matrix[i] & matrix[row]) == matrix[row])
 | |
|             return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| inline
 | |
| static void _register_key(uint8_t key)
 | |
| {
 | |
|     uint8_t col, row;
 | |
|     col = key&0x07;
 | |
|     row = (key>>3)&0x0F;
 | |
|     if (key&0x80) {
 | |
|         matrix[row] &= ~(1<<col);
 | |
|     } else {
 | |
|         matrix[row] |=  (1<<col);
 | |
|     }
 | |
| }
 |