Parent directory

matrix.c

6308 bytes
  1/**
  2 * matrix.c
  3 *
  4  Copyright 2020 astro <yuleiz@gmail.com>
  5    This program is free software: you can redistribute it and/or modify
  6    it under the terms of the GNU General Public License as published by
  7    the Free Software Foundation, either version 2 of the License, or
  8    (at your option) any later version.
  9    This program is distributed in the hope that it will be useful,
 10    but WITHOUT ANY WARRANTY; without even the implied warranty of
 11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12    GNU General Public License for more details.
 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 "print.h"
 18#include "bitwise.h"
 19#include "wait.h"
 20
 21#ifndef DEBOUNCE
 22#    define DEBOUNCE 5
 23#endif
 24
 25static uint8_t debouncing = DEBOUNCE;
 26
 27static matrix_row_t matrix[MATRIX_ROWS];
 28static matrix_row_t matrix_debouncing[MATRIX_ROWS];
 29
 30static uint8_t read_rows(void);
 31static void init_rows(void);
 32static void init_cols(void);
 33static void unselect_cols(void);
 34static void select_col(uint8_t col);
 35
 36
 37__attribute__ ((weak))
 38void matrix_init_kb(void)
 39{
 40    matrix_init_user();
 41}
 42
 43__attribute__ ((weak))
 44void matrix_scan_kb(void)
 45{
 46    matrix_scan_user();
 47}
 48
 49__attribute__ ((weak))
 50void matrix_init_user(void) {}
 51
 52__attribute__ ((weak))
 53void matrix_scan_user(void) {}
 54
 55void matrix_init(void)
 56{
 57  //gpio_set_pin_output(F0);
 58  //gpio_write_pin_high(F0);
 59  gpio_set_pin_output(B4);
 60  gpio_write_pin_low(B4);
 61
 62  init_cols();
 63  init_rows();
 64
 65  for (uint8_t i=0; i < MATRIX_ROWS; i++)  {
 66    matrix[i] = 0;
 67    matrix_debouncing[i] = 0;
 68  }
 69
 70  matrix_init_kb();
 71}
 72
 73uint8_t matrix_scan(void)
 74{
 75  for (uint8_t col = 0; col < MATRIX_COLS; col++) {
 76    select_col(col);
 77    _delay_us(3);
 78
 79    uint8_t rows = read_rows();
 80
 81    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
 82      bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
 83      bool curr_bit = rows & (1<<row);
 84      if (prev_bit != curr_bit) {
 85        matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
 86        debouncing = DEBOUNCE;
 87      }
 88    }
 89    unselect_cols();
 90  }
 91
 92  if (debouncing) {
 93    if (--debouncing) {
 94      _delay_ms(1);
 95    } else {
 96      for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
 97        matrix[i] = matrix_debouncing[i];
 98      }
 99    }
100  }
101
102  matrix_scan_kb();
103  return 1;
104}
105
106inline matrix_row_t matrix_get_row(uint8_t row)
107{
108  return matrix[row];
109}
110
111void matrix_print(void)
112{
113  print("\nr/c 0123456789ABCDEF\n");
114  for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
115    xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row)));
116  }
117}
118
119/*
120 * Row pin configuration
121 * row: 0    1    2    3    4
122 * pin: PE6  PF6  PF7  PB7  PD4
123 */
124static void init_rows(void)
125{
126  gpio_set_pin_input_high(E6);
127  gpio_set_pin_input_high(F6);
128  gpio_set_pin_input_high(F7);
129  gpio_set_pin_input_high(B7);
130  gpio_set_pin_input_high(D4);
131}
132
133static uint8_t read_rows(void)
134{
135  return ((gpio_read_pin(E6) ? 0 : (1 << 0)) |
136          (gpio_read_pin(F6) ? 0 : (1 << 1)) |
137          (gpio_read_pin(F7) ? 0 : (1 << 2)) |
138          (gpio_read_pin(B7) ? 0 : (1 << 3)) |
139          (gpio_read_pin(D4) ? 0 : (1 << 4)));
140}
141
142/*
143 * Columns 0 - 13
144 * These columns uses two 74LVC138 3 to 8 bit demultiplexers.
145 * EN Pin, PF5, PD6
146 *
147 * col / pin:    PF0  PF1  PF4
148 * 0:             0    0    0
149 * 1:             1    0    0
150 * 2:             0    1    0
151 * 3:             1    1    0
152 * 4:             0    0    1
153 * 5:             1    0    1
154 * 6:             0    1    1
155 *               PD2  PD3  PD5
156 * 7:             0    0    0
157 * 8:             1    0    0
158 * 9:             0    1    0
159 * 10:            1    1    0
160 * 11:            0    0    1
161 * 12:            1    0    1
162 * 13:            0    1    1
163 *
164 */
165static void init_cols(void)
166{
167  gpio_set_pin_output(F0);
168  gpio_set_pin_output(F1);
169  gpio_set_pin_output(F4);
170  gpio_set_pin_output(F5);
171
172  gpio_set_pin_output(D2);
173  gpio_set_pin_output(D3);
174  gpio_set_pin_output(D5);
175  gpio_set_pin_output(D6);
176
177  unselect_cols();
178}
179
180static void unselect_cols(void)
181{
182  gpio_write_pin_high(F0);
183  gpio_write_pin_high(F1);
184  gpio_write_pin_high(F4);
185  gpio_write_pin_high(F5);
186
187  gpio_write_pin_high(D2);
188  gpio_write_pin_high(D3);
189  gpio_write_pin_high(D5);
190  gpio_write_pin_high(D6);
191}
192
193static void select_col(uint8_t col) {
194
195   switch (col) {
196        case 0:
197          gpio_write_pin_low(F0);
198          gpio_write_pin_low(F1);
199          gpio_write_pin_low(F4);
200          break;
201        case 1:
202          gpio_write_pin_high(F0);
203          gpio_write_pin_low(F1);
204          gpio_write_pin_low(F4);
205          break;
206        case 2:
207          gpio_write_pin_low(F0);
208          gpio_write_pin_high(F1);
209          gpio_write_pin_low(F4);
210          break;
211        case 3:
212          gpio_write_pin_high(F0);
213          gpio_write_pin_high(F1);
214          gpio_write_pin_low(F4);
215          break;
216        case 4:
217          gpio_write_pin_low(F0);
218          gpio_write_pin_low(F1);
219          gpio_write_pin_high(F4);
220          break;
221        case 5:
222          gpio_write_pin_high(F0);
223          gpio_write_pin_low(F1);
224          gpio_write_pin_high(F4);
225          break;
226        case 6:
227          gpio_write_pin_low(F0);
228          gpio_write_pin_high(F1);
229          gpio_write_pin_high(F4);
230          break;
231        case 7:
232          gpio_write_pin_low(D2);
233          gpio_write_pin_low(D3);
234          gpio_write_pin_low(D5);
235          break;
236        case 8:
237          gpio_write_pin_high(D2);
238          gpio_write_pin_low(D3);
239          gpio_write_pin_low(D5);
240          break;
241        case 9:
242          gpio_write_pin_low(D2);
243          gpio_write_pin_high(D3);
244          gpio_write_pin_low(D5);
245          break;
246        case 10:
247          gpio_write_pin_high(D2);
248          gpio_write_pin_high(D3);
249          gpio_write_pin_low(D5);
250          break;
251        case 11:
252          gpio_write_pin_low(D2);
253          gpio_write_pin_low(D3);
254          gpio_write_pin_high(D5);
255          break;
256        case 12:
257          gpio_write_pin_high(D2);
258          gpio_write_pin_low(D3);
259          gpio_write_pin_high(D5);
260          break;
261        case 13:
262          gpio_write_pin_low(D2);
263          gpio_write_pin_high(D3);
264          gpio_write_pin_high(D5);
265          break;
266    }
267}