Custom Matrix 
QMK provides a mechanism to supplement or replace the default matrix scanning routine with your own code.
The reasons to use this feature include:
- Extra hardware between the keyboard's switches and MCU pins - I/O multiplexer
- Line decoder
 
- Irregular switch matrix - Simultaneous use of COL2ROWandROW2COL
 
- Simultaneous use of 
Prerequisites 
Implementing custom matrix usually involves compilation of an additional source file. It is recommended that for consistency, this file is called matrix.c.
Add a new file to your keyboard directory:
keyboards/<keyboard>/matrix.cAnd to configure compilation for the new file, add this to your rules.mk:
SRC += matrix.c'lite' 
Provides a default implementation for various scanning functions, reducing the boilerplate code when implementing custom matrix. To configure it, add this to your rules.mk:
CUSTOM_MATRIX = liteAnd implement the following functions in a matrix.c file in your keyboard folder:
void matrix_init_custom(void) {
    // TODO: initialize hardware here
}
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    bool matrix_has_changed = false;
    // TODO: add matrix scanning routine here
    return matrix_has_changed;
}Full Replacement 
When more control over the scanning routine is required, you can choose to implement the full scanning routine. To configure it, add this to your rules.mk:
CUSTOM_MATRIX = yesAnd implement the following functions in a matrix.c file in your keyboard folder:
matrix_row_t matrix_get_row(uint8_t row) {
    // TODO: return the requested row data
}
void matrix_print(void) {
    // TODO: use print() to dump the current matrix state to console
}
void matrix_init(void) {
    // TODO: initialize hardware and global matrix state here
    // Unless hardware debouncing - Init the configured debounce routine
    debounce_init(MATRIX_ROWS);
    // This *must* be called for correct keyboard behavior
    matrix_init_kb();
}
uint8_t matrix_scan(void) {
    bool changed = false;
    // TODO: add matrix scanning routine here
    // Unless hardware debouncing - use the configured debounce routine
    changed = debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
    // This *must* be called for correct keyboard behavior
    matrix_scan_kb();
    return changed;
}And also provide defaults for the following callbacks:
__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) {}