Advertisement
hakbraley

QMK Demultiplexer Matrix Scanning

Jul 8th, 2022
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.80 KB | None | 0 0
  1. /*  https://www.reddit.com/r/olkb/comments/vthz1k/help_with_my_custom_matrix_for_demultiplexer/
  2.  *  Code to scan a keyboard matrix using three 74HC238 demultiplexer chips.
  3.  */
  4.  
  5.  
  6. /* This should go into config.h
  7.  *
  8.  * #define MATRIX_ROWS 11
  9.  * #define MATRIX_COLS 20
  10.  *
  11.  * #define MATRIX_ROW_PINS {B3, A10, B15, B14, B9, B12, B4, B5, B6, B7, B8}
  12.  * #define MATRIX_COL_PINS {NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN}
  13.  *
  14.  * #define DMUX_SELECT_PINS {A5, C13, C14}
  15.  * #define NUM_DMUX_SELECT_PINS 3
  16.  *
  17.  * #define DMUX_ENABLE_PINS {C15, A0}
  18.  * #define NUM_DMUX_ENABLE_PINS 2
  19.  *
  20.  */
  21.  
  22.  
  23. // In matrix.c ----------------------------------------------------------------
  24.  
  25. /* This keyboard uses three 74HC238 demultiplexer chips to scan the columns of its matrix.
  26.  * Columns 0-7  will use the first chip, enabled by a pullup resistor.
  27.  * Columns 8-15 will use the second chip by writing to its enable pin, disabling the other 2 chips.
  28.  * Columns 8-19 will use the third chip by writing to its enable pin, disabling the other 2 chips.
  29.  *
  30.  * The select pins are then used to produce output at the specified column.
  31.  */
  32.  
  33. #include <stdint.h>
  34. #include <stdbool.h>
  35. #include "quantum.h"
  36. #include "wait.h"
  37. #include "matrix.h"
  38.  
  39.  
  40. // Arrays of the pins to be used
  41. static const pin_t row_pins[MATRIX_ROWS] = ROW_PINS;
  42. static const pin_t dmux_select_pins[NUM_DMUX_SELECT_PINS] = DMUX_SELECT_PINS;
  43. static const pin_t dmux_enable_pins[NUM_DMUX_ENABLE_PINS] = DMUX_ENABLE_PINS;
  44.  
  45.  
  46. // Initialize pins to be used for matrix scanning
  47. void matrix_init_custom(void) {
  48.     // Set all row_pins to inputs, with pulldown resistors to detect HIGH values from columns
  49.     for (int row = 0; row < MATRIX_ROWS; row++) {
  50.         setPinInputLow(row_pins[row]);
  51.     }
  52.  
  53.     // Set all dmux_select_pins to outputs, and write LOW
  54.     for (int pin = 0; pin < NUM_DMUX_SELECT_PINS; pin++) {
  55.         setPinOutput(dmux_select_pins[pin]);
  56.         writePinLow(dmux_select_pins[pin]);
  57.     }
  58.  
  59.     // Set all dmux_enable_pins to outputs, and write LOW
  60.     for (int pin = 0; pin < NUM_DMUX_ENABLE_PINS; pin++) {
  61.         setPinOutput(dmux_enable_pins[pin]);
  62.         writePinLow(dmux_enable_pins[pin]);
  63.     }
  64. }
  65.  
  66.  
  67. /* In binary, the first 3 bits of a number refer to its value between 0-7
  68.  * These are written to the dmux_select_pins.
  69.  *
  70.  * The 4th bit is active for columns 8-15, in which case the first dmux_enable_pin is set
  71.  * The 5th bit is active for columns 16-19, in which case the second dmux_enable_pin is set
  72.  */
  73.  
  74. // Write dmux pins in order to produce output at specified column
  75. static void select_column(uint8_t col_index) {
  76.     writePin(dmux_select_pins[0], col_index & 0b001);  // is 1st bit of col_index true?
  77.     writePin(dmux_select_pins[1], col_index & 0b010);  // is 2nd bit of col_index true?
  78.     writePin(dmux_select_pins[2], col_index & 0b100);  // is 3rd bit of col_index true?
  79.  
  80.     writePin(dmux_enable_pins[0], col_index & 8);      // is 4th bit of col_index true?
  81.     writePin(dmux_enable_pins[1], col_index & 16);     // is 5th bit of col_index true?
  82.  
  83.     wait_us(0.015);  // Wait 0.015 microseconds to propagate the signal
  84. }
  85.  
  86.  
  87. static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
  88.     bool matrix_changed = false;
  89.  
  90.     // For each row
  91.     for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
  92.         // Store last value of row prior to reading
  93.         matrix_row_t last_row_value    = current_matrix[row_index];
  94.         matrix_row_t current_row_value = last_row_value;
  95.  
  96.         // Check row pin state
  97.         if (readPin(row_pins[row_index]) == 1) {
  98.             // HIGH signal from column means a key is pressed, set column bit
  99.             current_row_value |= (MATRIX_ROW_SHIFTER << current_col);
  100.         } else {
  101.             // No signal from column means no key is pressed, clear column bit
  102.             current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col);
  103.         }
  104.  
  105.         // Determine if the matrix changed state, update current_matrix if needed
  106.         if ((last_row_value != current_row_value)) {
  107.             matrix_changed = true;
  108.             current_matrix[row_index] = current_row_value;
  109.         }
  110.     }
  111.  
  112.     return matrix_changed;  // True if any rows had a change, otherwise false
  113. }
  114.  
  115.  
  116. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  117.     bool matrix_has_changed = false;
  118.    
  119.     // For each column
  120.     for (uint8_t col = 0; col < MATRIX_COLS; col++) {
  121.         // Write dmux_pins for current column
  122.         select_column(col);
  123.        
  124.         // Read the rows for this column.  
  125.         // If any rows have changed, matrix_has_changed will be true
  126.         matrix_has_changed |= read_rows_on_col(current_matrix, col);
  127.     }
  128.    
  129.     return matrix_has_changed;
  130. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement