qmk-firmwares/keyboards/fujitsu/fmr60kb111/matrix.c

271 lines
5.5 KiB
C

#include "quantum.h"
#include "print.h"
/*
- A & B chooses which demux to use
- C, D & E are used for choosing column
SN54LS139AN
2G = always low (enabled)
A B -> H G F
0 0 0 1 1
0 1 1 0 1
1 0 1 1 0
1 1 1 1 1
1G = F (high disables)
D E -> K J I
0 0 0 1 1
0 1 1 0 1
1 0 1 1 0
1 1 1 1 1
SN54LS139AN feeds 215N_A (G) and 215N_B (H)
215N_A (G high disables)
G C D E -> S R Q P O N M L
0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 1 1 0 1 1 1 1 1 1
0 0 1 0 1 1 0 1 1 1 1 1
0 0 1 1 1 1 1 0 1 1 1 1
0 1 0 0 1 1 1 1 0 1 1 1
0 1 0 1 1 1 1 1 1 0 1 1
0 1 1 0 1 1 1 1 1 1 0 1
0 1 1 1 1 1 1 1 1 1 1 0
1 X X X 1 1 1 1 1 1 1 1
215N_B (H high disables)
H C D E -> Ö Ä Å Z Y V U T
0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 1 1 0 1 1 1 1 1 1
0 0 1 0 1 1 0 1 1 1 1 1
0 0 1 1 1 1 1 0 1 1 1 1
0 1 0 0 1 1 1 1 0 1 1 1
0 1 0 1 1 1 1 1 1 0 1 1
0 1 1 0 1 1 1 1 1 1 0 1
0 1 1 1 1 1 1 1 1 1 1 0
1 X X X 1 1 1 1 1 1 1 1
*/
// Column selection pins
#define COL_A F7
#define COL_B F6
#define COL_C F5
#define COL_D F4
#define COL_E F1
// Read pins
#define RD_A C6
#define RD_B D7
#define RD_C E6
#define RD_D B4
#define RD_E B5
#define RD_F B6
#define RD_G B7
#define RD_H D6
#define D139_START 0
#define D139_PINS 3
#define D215_A_START D139_PINS
#define D215_A_PINS 8
#define D215_B_START D215_A_START + D215_A_PINS
#define D215_B_PINS 8
enum Demux {
// SN54LS139AN
D139,
// SN74LS145N (first)
D215_A,
// SN74LS145N (second)
D215_B,
// All scanned
END
};
static uint8_t current_col[MATRIX_ROWS];
enum Demux next_demux(enum Demux current_demux) {
switch (current_demux) {
case D139: return D215_A;
case D215_A: return D215_B;
default: return END;
}
}
void select_demux(enum Demux demux) {
switch (demux) {
case D139:
writePinHigh(COL_A);
writePinLow(COL_B);
break;
case D215_A:
writePinLow(COL_A);
writePinHigh(COL_B);
break;
case D215_B:
writePinLow(COL_A);
writePinLow(COL_B);
default:
// This will never happen, trust me bro
return;
}
}
uint8_t readMatrixPin(pin_t pin) {
return (readPin(pin) == 0) ? 0 : 1;
}
void readPins(uint8_t out[]) {
out[0] = readMatrixPin(RD_A);
out[1] = readMatrixPin(RD_B) << 1;
out[2] = readMatrixPin(RD_C) << 2;
out[3] = readMatrixPin(RD_D) << 3;
out[4] = readMatrixPin(RD_E) << 4;
out[5] = readMatrixPin(RD_F) << 5;
out[6] = readMatrixPin(RD_G) << 6;
out[7] = readMatrixPin(RD_H) << 7;
}
bool readColumn(matrix_row_t current_matrix[], uint8_t col) {
bool changed = false;
readPins(current_col);
for (uint8_t r = 0; r < MATRIX_ROWS; ++r) {
uint8_t old_val = (current_matrix[r] >> col) & 0x1;
uint8_t new_val = current_col[r];
if (old_val != new_val) {
changed = true;
if (new_val == 1) {
current_matrix[r] |= (1U << col);
} else {
current_matrix[r] &= ~(1U << col);
}
}
}
return changed;
}
bool scan_d139(matrix_row_t current_matrix[]) {
bool changed = false;
for (uint8_t i = D139_START; i < D139_PINS; ++i) {
if (i == 0) {
writePinLow(COL_D);
writePinLow(COL_E);
} else if (i == 1) {
writePinLow(COL_D);
writePinHigh(COL_E);
} else {
writePinHigh(COL_D);
writePinLow(COL_E);
}
wait_us(5);
changed = readColumn(current_matrix, i) || changed;
}
return changed;
}
bool scan_d215(matrix_row_t current_matrix[], uint8_t col_start, uint8_t pins) {
bool changed = false;
for (uint8_t i = col_start; i < pins; ++i) {
uint8_t local_i = i - col_start;
if (local_i & 0x1) {
writePinHigh(COL_E);
} else {
writePinLow(COL_E);
}
if (local_i & 0x2) {
writePinHigh(COL_D);
} else {
writePinLow(COL_D);
}
if (local_i & 0x4) {
writePinHigh(COL_C);
} else {
writePinLow(COL_C);
}
wait_us(5);
changed = readColumn(current_matrix, i) || changed;
}
return changed;
}
bool scan_d215_a(matrix_row_t current_matrix[]) {
return scan_d215(current_matrix, D215_A_START, D215_A_PINS);
}
bool scan_d215_b(matrix_row_t current_matrix[]) {
return scan_d215(current_matrix, D215_B_START, D215_B_PINS);
}
bool scan_demux(matrix_row_t current_matrix[], enum Demux demux) {
switch (demux) {
case D139: return scan_d139(current_matrix);
case D215_A: return scan_d215_a(current_matrix);
case D215_B: return scan_d215_b(current_matrix);
default: return false;
}
}
void matrix_init_custom(void) {
setPinInputHigh(RD_A);
setPinInputHigh(RD_B);
setPinInputHigh(RD_C);
setPinInputHigh(RD_D);
setPinInputHigh(RD_E);
setPinInputHigh(RD_F);
setPinInputHigh(RD_G);
setPinInputHigh(RD_H);
setPinOutput(COL_A);
setPinOutput(COL_B);
setPinOutput(COL_C);
setPinOutput(COL_D);
setPinOutput(COL_E);
writePinLow(COL_A);
writePinLow(COL_B);
writePinLow(COL_C);
writePinLow(COL_D);
writePinLow(COL_E);
wait_us(20);
print("Init finished\n");
}
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
static uint16_t counter = 0;
bool matrix_has_changed = false;
enum Demux active_demux = D139;
++counter;
do {
select_demux(active_demux);
matrix_has_changed = scan_demux(current_matrix, active_demux) || matrix_has_changed;
if (counter % 1000 == 0) {
printf("Checking demux %d, %i\n", active_demux, matrix_has_changed);
counter = 0;
}
active_demux = next_demux(active_demux);
} while (active_demux != END);
return matrix_has_changed;
}