2017-10-10 11:07:59 -06:00
/*
Copyright 2012 Jun Wako
Copyright 2014 Jack Humbert
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/>.
*/
#include <stdint.h>
#include <stdbool.h>
#if defined(__AVR__)
#include <avr/io.h>
#endif
#include "wait.h"
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"
#include "timer.h"
2018-12-05 19:31:21 -07:00
#include "dichotomy.h"
#include "pointing_device.h"
#include "report.h"
2021-02-06 09:20:48 +11:00
#include "protocol/serial.h"
2017-10-10 11:07:59 -06:00
#if (MATRIX_COLS <= 8)
# define print_matrix_header() print("\nr/c 01234567\n")
# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
# define matrix_bitpop(i) bitpop(matrix[i])
# define ROW_SHIFTER ((uint8_t)1)
#elif (MATRIX_COLS <= 16)
# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
# define matrix_bitpop(i) bitpop16(matrix[i])
# define ROW_SHIFTER ((uint16_t)1)
#elif (MATRIX_COLS <= 32)
# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
# define matrix_bitpop(i) bitpop32(matrix[i])
# define ROW_SHIFTER ((uint32_t)1)
#endif
#define MAIN_ROWMASK 0xFFF0;
2018-12-05 19:31:21 -07:00
#define LOWER_ROWMASK 0x3FC0;
2017-10-10 11:07:59 -06:00
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix [ MATRIX_ROWS ];
2018-12-05 19:31:21 -07:00
__attribute__ (( weak ))
void matrix_init_quantum ( void ) {
matrix_init_kb ();
}
__attribute__ (( weak ))
void matrix_scan_quantum ( void ) {
matrix_scan_kb ();
}
2017-10-10 11:07:59 -06:00
__attribute__ (( weak ))
void matrix_init_kb ( void ) {
matrix_init_user ();
}
__attribute__ (( weak ))
void matrix_scan_kb ( void ) {
matrix_scan_user ();
}
__attribute__ (( weak ))
void matrix_init_user ( void ) {
}
__attribute__ (( weak ))
void matrix_scan_user ( void ) {
}
inline
uint8_t matrix_rows ( void ) {
return MATRIX_ROWS ;
}
inline
uint8_t matrix_cols ( void ) {
return MATRIX_COLS ;
}
void matrix_init ( void ) {
matrix_init_quantum ();
2021-02-06 09:20:48 +11:00
serial_init ();
2017-10-10 11:07:59 -06:00
}
uint8_t matrix_scan ( void )
{
2018-12-05 19:31:21 -07:00
//xprintf("\r\nTRYING TO SCAN");
2017-10-10 11:07:59 -06:00
uint32_t timeout = 0 ;
//the s character requests the RF slave to send the matrix
SERIAL_UART_DATA = 's' ;
//trust the external keystates entirely, erase the last data
2018-12-05 19:31:21 -07:00
uint8_t uart_data [ 11 ] = { 0 };
2017-10-10 11:07:59 -06:00
//there are 10 bytes corresponding to 10 columns, and an end byte
2018-12-05 19:31:21 -07:00
for ( uint8_t i = 0 ; i < 11 ; i ++ ) {
2017-10-10 11:07:59 -06:00
//wait for the serial data, timeout if it's been too long
//this only happened in testing with a loose wire, but does no
//harm to leave it in here
while ( ! SERIAL_UART_RXD_PRESENT ){
timeout ++ ;
if ( timeout > 10000 ){
2018-12-05 19:31:21 -07:00
xprintf ( " \r\n Time out in keyboard." );
2017-10-10 11:07:59 -06:00
break ;
}
2018-12-05 19:31:21 -07:00
}
2017-10-10 11:07:59 -06:00
uart_data [ i ] = SERIAL_UART_DATA ;
}
//check for the end packet, the key state bytes use the LSBs, so 0xE0
//will only show up here if the correct bytes were recieved
2018-12-05 19:31:21 -07:00
uint8_t checksum = 0x00 ;
for ( uint8_t z = 0 ; z < 10 ; z ++ ){
checksum = checksum ^ uart_data [ z ];
}
checksum = checksum ^ ( uart_data [ 10 ] & 0xF0 );
// Smash the checksum from 1 byte into 4 bits
checksum = ( checksum ^ (( checksum & 0xF0 ) >> 4 )) & 0x0F ;
//xprintf("\r\nGOT RAW PACKET: \r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d",uart_data[0],uart_data[1],uart_data[2],uart_data[3],uart_data[4],uart_data[5],uart_data[6],uart_data[7],uart_data[8],uart_data[9],uart_data[10],checksum);
if (( uart_data [ 10 ] & 0x0F ) == checksum ) { //this is an arbitrary binary checksum (1001) (that would be 0x9.)
//xprintf("\r\nGOT PACKET: \r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d",uart_data[0],uart_data[1],uart_data[2],uart_data[3],uart_data[4],uart_data[5]);
2017-10-10 11:07:59 -06:00
//shifting and transferring the keystates to the QMK matrix variable
//bits 1-12 are row 1, 13-24 are row 2, 25-36 are row 3,
//bits 37-42 are row 4 (only 6 wide, 1-3 are 0, and 10-12 are 0)
//bits 43-48 are row 5 (same as row 4)
/* ASSUMING MSB FIRST */
matrix [ 0 ] = ((( uint16_t ) uart_data [ 0 ] << 8 ) | (( uint16_t ) uart_data [ 1 ])) & MAIN_ROWMASK ;
matrix [ 1 ] = (( uint16_t ) uart_data [ 1 ] << 12 ) | (( uint16_t ) uart_data [ 2 ] << 4 );
matrix [ 2 ] = ((( uint16_t ) uart_data [ 3 ] << 8 ) | (( uint16_t ) uart_data [ 4 ])) & MAIN_ROWMASK ;
matrix [ 3 ] = ((( uint16_t ) uart_data [ 4 ] << 9 ) | (( uint16_t ) uart_data [ 5 ] << 1 )) & LOWER_ROWMASK ;
2018-12-05 19:31:21 -07:00
matrix [ 4 ] = ((( uint16_t ) uart_data [ 5 ] << 7 ) | (( uart_data [ 10 ] & 1 << 7 ) ? 1 : 0 ) << 13 | (( uart_data [ 10 ] & 1 << 6 ) ? 1 : 0 ) << 6 ) & LOWER_ROWMASK ;
2017-10-10 11:07:59 -06:00
/* OK, TURNS OUT THAT WAS A BAD ASSUMPTION */
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i ++ ) {
//I've unpacked these into the mirror image of what QMK expects them to be, so...
2018-12-05 19:31:21 -07:00
/*uint8_t halfOne = (matrix[i]>>8);
uint8_t halfTwo = (matrix[i] & 0xFF);
halfOne = ((halfOne * 0x0802LU & 0x22110LU) | (halfOne * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
halfTwo = ((halfTwo * 0x0802LU & 0x22110LU) | (halfTwo * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
matrix[i] = ((halfTwo<<8) & halfOne);*/
//matrix[i] = ((matrix[i] * 0x0802LU & 0x22110LU) | (matrix[i] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
matrix [ i ] = bitrev16 ( matrix [ i ]);
2017-10-10 11:07:59 -06:00
//bithack mirror! Doesn't make any sense, but works - and efficiently.
}
2018-12-05 19:31:21 -07:00
//if (uart_data[6]!=0 || uart_data[7]!=0){
//if (maxCount<101){
// xprintf("\r\nMouse data: x=%d, y=%d",(int8_t)uart_data[6],(int8_t)uart_data[7]);
//}
report_mouse_t currentReport = {};
//check for the end packet, bytes 1-4 are movement and scroll
//but byte 5 has bits 0-3 for the scroll button state
//(1000 if pressed, 0000 if not) and bits 4-7 are always 1
//We can use this to verify the report sent properly.
2017-10-10 11:07:59 -06:00
2018-12-05 19:31:21 -07:00
currentReport = pointing_device_get_report ();
//shifting and transferring the info to the mouse report varaible
//mouseReport.x = 127 max -127 min
currentReport . x = ( int8_t ) uart_data [ 6 ];
//mouseReport.y = 127 max -127 min
currentReport . y = ( int8_t ) uart_data [ 7 ];
//mouseReport.v = 127 max -127 min (scroll vertical)
currentReport . v = ( int8_t ) uart_data [ 8 ];
//mouseReport.h = 127 max -127 min (scroll horizontal)
currentReport . h = ( int8_t ) uart_data [ 9 ];
/*
currentReport.x = 0;
currentReport.y = 0;
currentReport.v = 0;
currentReport.h = 0;*/
pointing_device_set_report ( currentReport );
} else {
//xprintf("\r\nRequested packet, data 10 was %d but checksum was %d",(uart_data[10] & 0x0F), (checksum & 0x0F));
}
//matrix_print();
2017-10-10 11:07:59 -06:00
matrix_scan_quantum ();
return 1 ;
}
inline
bool matrix_is_on ( uint8_t row , uint8_t col )
{
2019-01-27 16:30:25 +10:00
return ( matrix [ row ] & (( matrix_row_t ) 1 << col ));
2017-10-10 11:07:59 -06:00
}
inline
matrix_row_t matrix_get_row ( uint8_t row )
{
return matrix [ row ];
}
void matrix_print ( void )
{
print_matrix_header ();
for ( uint8_t row = 0 ; row < MATRIX_ROWS ; row ++ ) {
2021-02-06 16:56:13 +00:00
print_hex8 ( row ); print ( ": " );
2017-10-10 11:07:59 -06:00
print_matrix_row ( row );
print ( " \n " );
}
}
uint8_t matrix_key_count ( void )
{
uint8_t count = 0 ;
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i ++ ) {
count += matrix_bitpop ( i );
}
return count ;
}