diff options
Diffstat (limited to 'keyboards/hazel/bad_wings/matrix.c')
-rw-r--r-- | keyboards/hazel/bad_wings/matrix.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/keyboards/hazel/bad_wings/matrix.c b/keyboards/hazel/bad_wings/matrix.c new file mode 100644 index 0000000000..496bebd58f --- /dev/null +++ b/keyboards/hazel/bad_wings/matrix.c @@ -0,0 +1,137 @@ +// Copyright 2022 @sadekbaroudi (Sadek Baroudi) +// Copyright 2023 @jasonhazel (Jason Hazel) +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "quantum.h" +#include "spi_master.h" +#include <string.h> /* memset */ +#include <unistd.h> /* close */ +#include "quantum.h" +#include "matrix.h" + +#if (!defined(SHIFTREG_MATRIX_COL_CS)) +# error Missing shift register I/O pin definitions +#endif + +int matrixArraySize = SHIFTREG_ROWS * sizeof(matrix_row_t); +matrix_row_t oldMatrix[SHIFTREG_ROWS]; + +#define SHIFTREG_OUTPUT_BITS 8 +pin_t rowPinsSR[SHIFTREG_ROWS] = MATRIX_ROW_PINS_SR; + +// semaphore to make sure SPI doesn't get called multiple times +static bool shiftRegisterSPILocked = false; + +void semaphore_lock(bool value) { + shiftRegisterSPILocked = value; +} + +bool semaphore_is_locked(void) { + return shiftRegisterSPILocked; +} + +void sr_74hc595_spi_stop(void) { + spi_stop(); + semaphore_lock(false); +} + +bool sr_74hc595_spi_start(void) { + if (!spi_start(SHIFTREG_MATRIX_COL_CS, false, 0, SHIFTREG_DIVISOR)) { + dprintf("74hc595 matrix: failed to start spi\n"); + sr_74hc595_spi_stop(); + return false; + } + + semaphore_lock(true); + wait_us(1); // not sure if I need this + return true; +} + +bool sr_74hc595_spi_send_byte(uint8_t data) { + sr_74hc595_spi_start(); + writePinLow(SHIFTREG_MATRIX_COL_CS); + matrix_io_delay(); + spi_write(data); + matrix_io_delay(); + writePinHigh(SHIFTREG_MATRIX_COL_CS); + sr_74hc595_spi_stop(); + return true; +} + +/** + * Set the entire shift register to be full of inactive bits + */ +void clearColumns(void) { + uint8_t value = 0b00000000; + sr_74hc595_spi_send_byte(value); +} + +void setColumn(int columnShift, bool test_run) { + uint8_t columnShiftByte = ((uint8_t)1 << columnShift); + if(test_run) { + dprintf("byte sent: %d\n", columnShiftByte); + } + sr_74hc595_spi_send_byte(columnShiftByte); +} + +/* + * override of the qmk intialization function + */ +void matrix_init_custom(void) { + wait_ms(300); + spi_init(); + // Set up the initial states for all the row pins + for (int r = 0; r < SHIFTREG_ROWS; r++) { + // Note: This needs to use the internal pull down resistors, and atmegas do *not* support that + setPinInputLow(rowPinsSR[r]); + } + + // Set the CS to low by default, and specify as an output pin + writePinHigh(SHIFTREG_MATRIX_COL_CS); // should be high when using SPI? + setPinOutput(SHIFTREG_MATRIX_COL_CS); + + // Since it's the init, deactivate all the columns. We'll activate once we get to the matrix scan + clearColumns(); +} + +bool matrix_scan_custom(matrix_row_t current_matrix[]) { + // respect the semaphore + if (semaphore_is_locked()) { + return false; + } + + // Keep track of if something was modified + bool matrix_has_changed = false; + + // reset the current matrix, as we'll be updating and comparing to the old matrix + memset(current_matrix, 0, matrixArraySize); + + + bool debug_output = false; + // Loop through the columns, activating one at a time, and read the rows, and place in the new current_matrix + for (int c = 0; c < SHIFTREG_COLS; c++) { + if (debug_output) { + dprintf("column iteration: %d\n", c); + } + setColumn(c, debug_output); + matrix_io_delay(); + + for (int r = 0; r < SHIFTREG_ROWS; r++) { + current_matrix[r] |= ((readPin(rowPinsSR[r]) ? 1 : 0) << c); + } + } + + matrix_has_changed = memcmp(current_matrix, oldMatrix, matrixArraySize) != 0; + memcpy(oldMatrix, current_matrix, matrixArraySize); + + if (matrix_has_changed) { + matrix_print(); + } + + + // Deactivate all the columns for the next run. + clearColumns(); + matrix_io_delay(); + + return matrix_has_changed; +} |