summaryrefslogtreecommitdiffstats
path: root/keyboards/handwired/datahand/matrix.c
blob: afce07e10de2326e7d2c0e4dae62ffbcefa1f5d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* Copyright 2017-2019 Nikolaus Wittenstein <nikolaus.wittenstein@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include "datahand.h"

#include "matrix.h"
#include "action.h"

#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>

static matrix_row_t matrix[MATRIX_ROWS];

static matrix_row_t read_cols(void);
static void select_row(uint8_t row);

// user-defined overridable functions

__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) {}

// helper functions
void matrix_init(void) {
  /* See datahand.h for more detail on pins. */

  /* 7 - matrix scan; 6-3 - mode LEDs */
  DDRB = 0b11111000;

  /* 1-0 - matrix scan */
  DDRD = 0b00000011;

  /* 6 - matrix scan */
  DDRE = 0b01000000;

  /* 7-4 - lock LEDs */
  DDRF = 0b11110000;

  /* Turn off the non-Normal LEDs (they're active low). */
  PORTB |= LED_TENKEY | LED_FN | LED_NAS;

  /* Turn off the lock LEDs. */
  PORTF |= LED_CAPS_LOCK | LED_NUM_LOCK | LED_SCROLL_LOCK | LED_MOUSE_LOCK;

  matrix_init_kb();
}

uint8_t matrix_scan(void) {
  for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    select_row(row);
    /* The default hardware works down to at least 100us, but I have a replacement
     * photodiode that responds a little more slowly. Cranking it up to 1000us fixes
     * shadowing issues.
     */
    _delay_us(1000);
    matrix[row] = read_cols();
  }

  matrix_scan_kb();

  return 1;
}

matrix_row_t matrix_get_row(uint8_t row) {
  return matrix[row];
}

void matrix_print(void) {
  print("\nr/c 01234567\n");

  for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    print_hex8(row);
    print(": ");
    print_bin_reverse8(matrix_get_row(row));
    print("\n");
  }
}

static void select_row(uint8_t row) {
  /* Original 8051: P1 bits 0-3 (pins 1-4)
   * Teensy++: PE0, PB7, PD0, PD1
   */

  if (row & (1<<0)) {
    PORTE |= (1<<6);
  } else {
    PORTE &= ~(1<<6);
  }

  if (row & (1<<1)) {
    PORTB |= (1<<7);
  } else {
    PORTB &= ~(1<<7);
  }

  if (row & (1<<2)) {
    PORTD |= (1<<0);
  } else {
    PORTD &= ~(1<<0);
  }

  if (row & (1<<3)) {
    PORTD |= (1<<1);
  } else {
    PORTD &= ~(1<<1);
  }
}

static matrix_row_t read_cols(void) {
  /* Original 8051: P1 bits 4-7 (pins 5-8)
   * Teensy++: PD bits 2-5
   */

  return (PIND & 0b00111100) >> 2;
}