示例#1
0
uint8_t matrix_scan(void) {
    static matrix_row_t debouncing_matrix[MATRIX_ROWS];
    for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
        toggle_row(r);
        matrix_row_t state = read_cols();
        if (debouncing_matrix[r] != state) {
            debouncing_matrix[r] = state;
            debouncing_delay = DEBOUNCING_DELAY;
        }
        toggle_row(r);
    }
    if (debouncing_delay >= 0) {
        dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
        --debouncing_delay;
        if (debouncing_delay >= 0) {
            wait_ms(1);
        }
        else {
            for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
                matrix[r] = debouncing_matrix[r];
            }
        }
    }
    matrix_scan_quantum();
    return 1;
}
示例#2
0
uint8_t matrix_scan(void)
{
    if (mcp23018_status) { // if there was an error
        if (++mcp23018_reset_loop == 0) {
            // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
            // this will be approx bit more frequent than once per second
            print("trying to reset mcp23018\n");
            mcp23018_status = init_mcp23018();
            if (mcp23018_status) {
                print("left side not responding\n");
            } else {
                print("left side attached\n");
                frenchdev_blink_all_leds();
            }
        }
    }

#ifdef DEBUG_MATRIX_SCAN_RATE
    matrix_scan_count++;

    uint32_t timer_now = timer_read32();
    if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
        print("matrix scan frequency: ");
        pdec(matrix_scan_count);
        print("\n");

        matrix_timer = timer_now;
        matrix_scan_count = 0;
    }
#endif

    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        select_row(i);
        wait_us(30);  // without this wait read unstable value.
        matrix_row_t cols = read_cols(i);
        if (matrix_debouncing[i] != cols) {
            matrix_debouncing[i] = cols;
            if (debouncing) {
                debug("bounce!: "); debug_hex(debouncing); debug("\n");
            }
            debouncing = DEBOUNCE;
        }
        unselect_rows();
    }

    if (debouncing) {
        if (--debouncing) {
            wait_us(1);
            // this should be wait_ms(1) but has been left as-is at EZ's request
        } else {
            for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
                matrix[i] = matrix_debouncing[i];
            }
        }
    }

    matrix_scan_quantum();

    return 1;
}
示例#3
0
uint8_t matrix_scan(void) {
  for (uint8_t col = 0; col < MATRIX_COLS; col++) {
    select_col(col);
    _delay_us(3);

    uint8_t rows = read_rows(col);

    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
      bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
      bool curr_bit = rows & (1<<row);
      if (prev_bit != curr_bit) {
        matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
        debouncing = DEBOUNCING_DELAY;
      }
    }
    unselect_cols();
  }

  if (debouncing) {
    if (--debouncing) {
      _delay_ms(1);
    } else {
      for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        matrix[i] = matrix_debouncing[i];
      }
    }
  }

  matrix_scan_quantum();
  return 1;
}
示例#4
0
uint8_t matrix_scan(void) {
  uint8_t ret = 0;
  ret |= i2c_read_hand(LEFT);
  ret |= i2c_read_hand(RIGHT);
  matrix_scan_quantum();
  return ret;
}
示例#5
0
uint8_t matrix_scan(void) {
  uint8_t ret = _matrix_scan();

  if (is_keyboard_master()) {
    static uint8_t error_count;

    if (!transport_master(matrix + thatHand)) {
      error_count++;

      if (error_count > ERROR_DISCONNECT_COUNT) {
        // reset other half if disconnected
        for (int i = 0; i < ROWS_PER_HAND; ++i) {
          matrix[thatHand + i] = 0;
        }
      }
    } else {
      error_count = 0;
    }

    matrix_scan_quantum();
  } else {
    transport_slave(matrix + thisHand);
#ifdef ENCODER_ENABLE
    encoder_read();
#endif
    matrix_slave_scan_user();
  }

  return ret;
}
示例#6
0
uint8_t matrix_scan(void)
{
    uint8_t mchanged;
    uint8_t row;
    uint8_t col;
    uint32_t scans[2]; //PA PB

    if (CLK_get_ms() < mdebouncing) return 1; //mdebouncing == 0 when no debouncing active

    //m15_off; //Profiling scans

    memset(mlatest, 0, MATRIX_ROWS * sizeof(matrix_row_t)); //Zero the result buffer

    for (col = 0; col < MATRIX_COLS; col++)
    {
        PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; //Set col output

        CLK_delay_us(MATRIX_SCAN_DELAY); //Delay for output

        scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; //Read PA row pins data
        scans[PB] = PORT->Group[PB].IN.reg & row_masks[PB]; //Read PB row pins data

        PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Clear col output

        for (row = 0; row < MATRIX_ROWS; row++)
        {
            //Move scan bits from scans array into proper row bit locations
            if (scans[row_ports[row]] & (1 << row_pins[row]))
                mlatest[row] |= 1 << col;
        }
    }

    mchanged = 0; //Default to no matrix change since last

    for (row = 0; row < MATRIX_ROWS; row++)
    {
        if (mlast[row] != mlatest[row])
            mchanged = 1;
        mlast[row] = mlatest[row];
    }

    if (!mchanged)
    {
        for (row = 0; row < MATRIX_ROWS; row++)
            mdebounced[row] = mlatest[row];
        mdebouncing = 0;
    }
    else
    {
        //Begin or extend debounce on change
        mdebouncing = CLK_get_ms() + DEBOUNCING_DELAY;
    }

    //m15_on; //Profiling scans

    matrix_scan_quantum();

    return 1;
}
示例#7
0
uint8_t matrix_scan(void) {

    // actual matrix scan
    for (uint8_t c = 0; c < MATRIX_ROWS; c++) {
        switch (c) {
          case 0:  PORTB &= ~(1 << 3); break;
          case 1:  PORTB &= ~(1 << 4); break;
          case 2:  PORTB &= ~(1 << 5); break;
          case 3:  PORTB &= ~(1 << 6); break;
          case 4:  PORTB &= ~(1 << 7); break;
        }
        _delay_us(5);

        matrix_row_t current_row = (
          (((PINA & (1 << 0)) ? 0 : 1 ) << 0)  |
          (((PINA & (1 << 1)) ? 0 : 1 ) << 1)  |
          (((PINA & (1 << 2)) ? 0 : 1 ) << 2)  |
          (((PINA & (1 << 3)) ? 0 : 1 ) << 3)  |
          (((PINA & (1 << 4)) ? 0 : 1 ) << 4)  |
          (((PINA & (1 << 5)) ? 0 : 1 ) << 5)  |
          (((PINA & (1 << 6)) ? 0 : 1 ) << 6)  |
          (((PINA & (1 << 7)) ? 0 : 1 ) << 7)  |
          (((PINC & (1 << 7)) ? 0 : 1 ) << 8)  |
          (((PINC & (1 << 6)) ? 0 : 1 ) << 9)  |
          (((PINC & (1 << 5)) ? 0 : 1 ) << 10) |
          (((PINC & (1 << 4)) ? 0 : 1 ) << 11) |
          (((PINC & (1 << 3)) ? 0 : 1 ) << 12) |
          (((PINC & (1 << 2)) ? 0 : 1 ) << 13) |
          (((PIND & (1 << 7)) ? 0 : 1 ) << 14)
        );

        switch (c) {
          case 0:  PORTB |= (1 << 3); break;
          case 1:  PORTB |= (1 << 4); break;
          case 2:  PORTB |= (1 << 5); break;
          case 3:  PORTB |= (1 << 6); break;
          case 4:  PORTB |= (1 << 7); break;
        }

        if (matrix_debouncing[c] != current_row) {
            matrix_debouncing[c] = current_row;
            debouncing = DEBOUNCE;
        }
    }

    if (debouncing) {
        if (--debouncing) {
            _delay_ms(1);
        } else {
            for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
                matrix[i] = matrix_debouncing[i];
            }
        }
    }

    matrix_scan_quantum();

    return 1;
}
uint8_t matrix_scan(void) {
  bool changed = custom_matrix_scan(raw_matrix);

  debounce(raw_matrix, matrix, MATRIX_ROWS, changed);

  matrix_scan_quantum();
  return 1;
}
示例#9
0
uint8_t matrix_scan(void)
{

#if (DIODE_DIRECTION == COL2ROW)

    // Set row, read cols
    for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
#       if (DEBOUNCING_DELAY > 0)
            bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);

            if (matrix_changed) {
                debouncing = true;
                debouncing_time = timer_read();
            }

#       else
            read_cols_on_row(matrix, current_row);
#       endif

    }

#elif (DIODE_DIRECTION == ROW2COL)

    // Set col, read rows
    for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
#       if (DEBOUNCING_DELAY > 0)
            bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
            if (matrix_changed) {
                debouncing = true;
                debouncing_time = timer_read();
            }
#       else
             read_rows_on_col(matrix, current_col);
#       endif

    }

#endif

#   if (DEBOUNCING_DELAY > 0)
        if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
            for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
                matrix[i] = matrix_debouncing[i];
            }
            debouncing = false;
        }
#   endif

    matrix_scan_quantum();
    return 1;
}
示例#10
0
uint8_t matrix_scan(void)
{
  bool changed = false;

#if (DIODE_DIRECTION == COL2ROW)
  // Set row, read cols
  for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    changed |= read_cols_on_row(raw_matrix, current_row);
  }
#elif (DIODE_DIRECTION == ROW2COL)
  // Set col, read rows
  for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
    changed |= read_rows_on_col(raw_matrix, current_col);
  }
#endif

  debounce(raw_matrix, matrix, MATRIX_ROWS, changed);

  matrix_scan_quantum();
  return 1;
}
示例#11
0
uint8_t matrix_scan(void)
{
    SERIAL_UART_INIT();

    uint32_t timeout = 0;

    //the s character requests the RF slave to send the matrix
    SERIAL_UART_DATA = 's';

    //trust the external keystates entirely, erase the last data
    uint8_t uart_data[14] = {0};

    //there are 10 bytes corresponding to 10 columns, and an end byte
    for (uint8_t i = 0; i < 14; i++) {
        //wait for the serial data, timeout if it's been too long
        //this only happened in testing with a loose wire, but does no
        //harm to leave it in here
        while(!SERIAL_UART_RXD_PRESENT){
            timeout++;
            if (timeout > 10000){
                break;
            }
        } 
        uart_data[i] = SERIAL_UART_DATA;
    }

    //check for the end packet, the key state bytes use the LSBs, so 0xE0
    //will only show up here if the correct bytes were recieved
    if (uart_data[10] == 0xE0)
    {
        //shifting and transferring the keystates to the QMK matrix variable
        for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
            matrix[i] = (uint16_t) uart_data[i*2] | (uint16_t) uart_data[i*2+1] << 6;
        }
    }


    matrix_scan_quantum();
    return 1;
}
示例#12
0
uint8_t matrix_scan(void) {
    // dip switch
    dip_switch[0] = !palReadPad(GPIOB, 14);
    dip_switch[1] = !palReadPad(GPIOA, 15);
    dip_switch[2] = !palReadPad(GPIOA, 10);
    dip_switch[3] = !palReadPad(GPIOB, 9);
    for (uint8_t i = 0; i < 4; i++) {
      if (last_dip_switch[i] ^ dip_switch[i])
        dip_update(i, dip_switch[i]);
    }
    memcpy(last_dip_switch, dip_switch, sizeof(&dip_switch));

    // encoder on B12 and B13
    encoder_state <<= 2;
    encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1);
    encoder_value += encoder_LUT[encoder_state & 0xF];
    if (encoder_value >= ENCODER_RESOLUTION) {
        encoder_update(0);
    }
    if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
        encoder_update(1);
    }
    encoder_value %= ENCODER_RESOLUTION;

    // actual matrix
    for (int col = 0; col < MATRIX_COLS; col++) {
        matrix_col_t data = 0;

        // strobe col { B11, B10, B2, B1, A7, B0 }
        switch (col) {
            case 0: palSetPad(GPIOB, 11); break;
            case 1: palSetPad(GPIOB, 10); break;
            case 2: palSetPad(GPIOB, 2); break;
            case 3: palSetPad(GPIOB, 1); break;
            case 4: palSetPad(GPIOA, 7); break;
            case 5: palSetPad(GPIOB, 0); break;
        }

        // need wait to settle pin state
        wait_us(20);

        // read row data { A10, A9, A8, B15, C13, C14, C15, A2 }
        data = (
            (palReadPad(GPIOA, 10) << 0 ) |
            (palReadPad(GPIOA, 9)  << 1 ) |
            (palReadPad(GPIOA, 8)  << 2 ) |
            (palReadPad(GPIOB, 15) << 3 ) |
            (palReadPad(GPIOC, 13) << 4 ) |
            (palReadPad(GPIOC, 14) << 5 ) |
            (palReadPad(GPIOC, 15) << 6 ) |
            (palReadPad(GPIOA, 2)  << 7 ) |
            (palReadPad(GPIOA, 3)  << 8 ) |
            (palReadPad(GPIOA, 6)  << 9 )
        );

        // unstrobe  col { B11, B10, B2, B1, A7, B0 }
        switch (col) {
            case 0: palClearPad(GPIOB, 11); break;
            case 1: palClearPad(GPIOB, 10); break;
            case 2: palClearPad(GPIOB, 2); break;
            case 3: palClearPad(GPIOB, 1); break;
            case 4: palClearPad(GPIOA, 7); break;
            case 5: palClearPad(GPIOB, 0); break;
        }

        if (matrix_debouncing[col] != data) {
            matrix_debouncing[col] = data;
            debouncing = true;
            debouncing_time = timer_read();
        }
    }

    if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
        for (int row = 0; row < MATRIX_ROWS; row++) {
            matrix[row] = 0;
            for (int col = 0; col < MATRIX_COLS; col++) {
                matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col);
            }
        }
        debouncing = false;
    }

    matrix_scan_quantum();

    return 1;
}
示例#13
0
uint8_t matrix_scan(void) {
    // encoder on B13 and B14
    encoder_state <<= 2;
    encoder_state |= (palReadPad(GPIOB, 13) << 0) | (palReadPad(GPIOB, 14) << 1);
    encoder_value += encoder_LUT[encoder_state & 0xF];
    if (encoder_value >= ENCODER_RESOLUTION) {
        encoder_update(0);
    }
    if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
        encoder_update(1);
    }
    encoder_value %= ENCODER_RESOLUTION;

    // actual matrix
    for (int col = 0; col < MATRIX_COLS; col++) {
        matrix_row_t data = 0;

        // strobe col { PB8, PB2, PB10, PA0, PA1, PA2, PB0, PA3, PB1, PA6, PA7, PB1, PA6, PA7, PB12, PC3, PB11,  }
        switch (col) {
            case 0:  palSetPad(GPIOB, 8); break;
            case 1:  palSetPad(GPIOB, 2); break;
            case 2:  palSetPad(GPIOB, 10); break;
            case 3:  palSetPad(GPIOA, 0); break;
            case 4:  palSetPad(GPIOA, 1); break;
            case 5:  palSetPad(GPIOA, 2); break;
            case 6:  palSetPad(GPIOB, 0); break;
            case 7:  palSetPad(GPIOA, 3); break;
            case 8:  palSetPad(GPIOB, 1); break;
            case 9:  palSetPad(GPIOA, 6); break;
            case 10: palSetPad(GPIOA, 7); break;
            case 11: palSetPad(GPIOB, 12); break;
            case 12: palSetPad(GPIOC, 13); break;
            case 13: palSetPad(GPIOB, 11); break;
            case 14: palSetPad(GPIOB, 9); break;
        }

        // need wait to settle pin state
        wait_us(20);

        // read row data { PC15, PC14, PA10, PA9, PA8 }
        data = (
            (palReadPad(GPIOC, 15)  << 0 ) |
            (palReadPad(GPIOC, 14)  << 1 ) |
            (palReadPad(GPIOA, 10)  << 2 ) |
            (palReadPad(GPIOA, 9)   << 3 ) |
            (palReadPad(GPIOA, 8)   << 4 )
        );

        // unstrobe  col { PB8, PB2, PB10, PA0, PA1, PA2, PB0, PA3, PB1, PA6, PA7, PB1, PA6, PA7, PB12, PC3, PB11,  }
        switch (col) {
            case 0:  palClearPad(GPIOB, 8); break;
            case 1:  palClearPad(GPIOB, 2); break;
            case 2:  palClearPad(GPIOB, 10); break;
            case 3:  palClearPad(GPIOA, 0); break;
            case 4:  palClearPad(GPIOA, 1); break;
            case 5:  palClearPad(GPIOA, 2); break;
            case 6:  palClearPad(GPIOB, 0); break;
            case 7:  palClearPad(GPIOA, 3); break;
            case 8:  palClearPad(GPIOB, 1); break;
            case 9:  palClearPad(GPIOA, 6); break;
            case 10: palClearPad(GPIOA, 7); break;
            case 11: palClearPad(GPIOB, 12); break;
            case 12: palClearPad(GPIOC, 13); break;
            case 13: palClearPad(GPIOB, 11); break;
            case 14: palClearPad(GPIOB, 9); break;
        }

        if (matrix_debouncing[col] != data) {
            matrix_debouncing[col] = data;
            debouncing = true;
            debouncing_time = timer_read();
        }
    }

    if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
        for (int row = 0; row < MATRIX_ROWS; row++) {
            matrix[row] = 0;
            for (int col = 0; col < MATRIX_COLS; col++) {
                matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col);
            }
        }
        debouncing = false;
    }

    matrix_scan_quantum();

    return 1;
}
示例#14
0
uint8_t matrix_scan(void)
{
    SERIAL_UART_INIT();

    uint32_t timeout = 0;

    // The 's' character requests the RF slave to send the matrix
    SERIAL_UART_DATA = 's';

    // Trust the external keystates entirely, erase the last data
    uint8_t uart_data[4] = {0};

    // There are 3 bytes corresponding to the data, and a checksum
    for (uint8_t i = 0; i < 4; i++) {
        // Wait for the serial data, timeout if it's been too long
        // This only happened in testing with a loose wire, but does no
        // harm to leave it in here
        while(!SERIAL_UART_RXD_PRESENT){
            timeout++;
            if (timeout > 10000){
                xprintf("\r\nTime out in keyboard.");
                break;
            }
        }
        uart_data[i] = SERIAL_UART_DATA;
    }

    // Check for the end packet, it's our checksum.
    // Will only be a match if the correct bytes were recieved
    if (uart_data[3] == (uart_data[0] ^ uart_data[1] ^ uart_data[2])) { // This is an arbitrary checksum calculated by XORing all the data.
        // Transferring the keystates to the QMK matrix variable
		/* ASSUMING MSB FIRST */
		matrix[0] = ((uint16_t) uart_data[0] << 8) | ((uint16_t) uart_data[1]);
		encoderValue += (int8_t) uart_data[2];
		if ((uart_data[0] | uart_data[1] | uart_data[2])!=0){
			xprintf("\r\n0x%0X%02X%02X",uart_data[0],uart_data[1], uart_data[2]);
		}
		/* OK, TURNS OUT THAT WAS A BAD ASSUMPTION */
        for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
			// I've unpacked these into the mirror image of what QMK expects them to be, so...
			matrix[i] = bitrev16(matrix[i]);
			// So I'll reverse it, and this should be fine now.
        }

        // A mouse report for scrolling would go here, but I don't plan on doing scrolling with the encoder. So.

    	report_mouse_t currentReport = {};
/*
    	currentReport = pointing_device_get_report();
            //mouseReport.x = 127 max -127 min
    	currentReport.x = (int8_t) uart_data[6];
            //mouseReport.y = 127 max -127 min
    	currentReport.y = (int8_t) uart_data[7];
            //mouseReport.v = 127 max -127 min (scroll vertical)
    	currentReport.v = (int8_t) uart_data[8];
            //mouseReport.h = 127 max -127 min (scroll horizontal)
    	currentReport.h = (int8_t) uart_data[9];
        */
    	/*
    	currentReport.x = 0;
    	currentReport.y = 0;
    	currentReport.v = 0;
        currentReport.h = 0;*/

        pointing_device_set_report(currentReport);
    } else {
        xprintf("\r\nRequested packet, data 3 was %d",uart_data[3]);
    }

    matrix_scan_quantum();
    return 1;
}
示例#15
0
uint8_t matrix_scan(void) {
    matrix_scan_quantum();
    return 1;
}
示例#16
0
uint8_t matrix_scan(void) {
    for (int col = 0; col < MATRIX_COLS; col++) {
        matrix_row_t data = 0;

        // strobe col { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC14, PC15, PC13, PB5, PB6 }
        switch (col) {
            case 0: palSetPad(GPIOA, 2); break;
            case 1: palSetPad(GPIOA, 3); break;
            case 2: palSetPad(GPIOA, 6); break;
            case 3: palSetPad(GPIOB, 14); break;
            case 4: palSetPad(GPIOB, 15); break;
            case 5: palSetPad(GPIOA, 8); break;
            case 6: palSetPad(GPIOA, 9); break;
            case 7: palSetPad(GPIOA, 7); break;
            case 8: palSetPad(GPIOB, 3); break;
            case 9: palSetPad(GPIOB, 4); break;
            case 10: palSetPad(GPIOC, 15); break;
            case 11: palSetPad(GPIOC, 14); break;
            case 12: palSetPad(GPIOC, 13); break;
            case 13: palSetPad(GPIOB, 5); break;
            case 14: palSetPad(GPIOB, 6); break;
        }

        // need wait to settle pin state
        wait_us(20);

        // read row data { PB0, PB1, PB2, PA15, PA10 }
        data = (
            (palReadPad(GPIOB, 0) << 0 ) |
            (palReadPad(GPIOB, 1) << 1 ) |
            (palReadPad(GPIOB, 2) << 2 ) |
            (palReadPad(GPIOA, 15) << 3 ) |
            (palReadPad(GPIOA, 10) << 4 )
        );

        // unstrobe  col { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC15, PC14, PC13, PB5, PB6 }
        switch (col) {
            case 0: palClearPad(GPIOA, 2); break;
            case 1: palClearPad(GPIOA, 3); break;
            case 2: palClearPad(GPIOA, 6); break;
            case 3: palClearPad(GPIOB, 14); break;
            case 4: palClearPad(GPIOB, 15); break;
            case 5: palClearPad(GPIOA, 8); break;
            case 6: palClearPad(GPIOA, 9); break;
            case 7: palClearPad(GPIOA, 7); break;
            case 8: palClearPad(GPIOB, 3); break;
            case 9: palClearPad(GPIOB, 4); break;
            case 10: palClearPad(GPIOC, 15); break;
            case 11: palClearPad(GPIOC, 14); break;
            case 12: palClearPad(GPIOC, 13); break;
            case 13: palClearPad(GPIOB, 5); break;
            case 14: palClearPad(GPIOB, 6); break;
        }

        if (matrix_debouncing[col] != data) {
            matrix_debouncing[col] = data;
            debouncing = true;
            debouncing_time = timer_read();
        }
    }

    if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
        for (int row = 0; row < MATRIX_ROWS; row++) {
            matrix[row] = 0;
            for (int col = 0; col < MATRIX_COLS; col++) {
                matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col);
            }
        }
        debouncing = false;
    }

    matrix_scan_quantum();

    return 1;
}