Update quantum matrix to support both AVR and Chibios ARM (#3968)

* Update quantum matrix to support both AVR and Chibios ARM

- Addition of STM32 pin definitions
- Created abstruction layer defines to control GPIO (This is a bit pointless for Chibios as we are creating a PAL ontop of a PAL but it is necessary for uniformity with AVR)
- Modified matrix.c to use the above functions

* minor ifdef fix

* Rename of functions and docs

- Added documentation.
- Renamed functions according to Jack's spec.

* Massdrop fix

* Update matrix.c

* Update quantum.h

* Update quantum.h

* Update quantum.h

* Update internals_gpio_control.md
This commit is contained in:
yiancar 2018-09-28 17:33:11 +01:00 committed by Jack Humbert
parent fa47f5fb15
commit 7fe03d085c
4 changed files with 244 additions and 96 deletions

View file

@ -0,0 +1,23 @@
# GPIO Control
QMK has a GPIO control abstraction layer which is micro-controller agnostic. This is done to allow easy access to pin control across different platforms.
## Functions
The following functions can provide basic control of GPIOs and are found in `quantum/quantum.h`.
|Function |Description |
|----------------------|------------------------------------------------------------------|
|`setPinInput(pin)` |Set pin as input with high impedance (High-Z) |
|`setPinInputHigh(pin)`|Set pin as input with build in pull-up |
|`setPinInputLow(pin)` |Set pin as input with build in pull-down (Supported only on STM32)|
|`setPinOutput(pin)` |Set pin as output |
|`writePinHige(pin)` |Set pin level as high, assuming it is an output |
|`writePinLow(pin)` |Set pin level as low, assuming it is an output |
|`writePin(pin, level)`|Set pin level, assuming it is an output |
|`readPin(pin)` |Returns the level of the pin |
## Advance settings
Each micro-controller can have multiple advance settings regarding its GPIO. This abstraction layer does not limit the use of architecture specific functions. Advance users should consult the datasheet of there desired device and include any needed libraries. For AVR the standard avr/io.h library is used and for STM32 the Chibios [PAL library](http://chibios.sourceforge.net/docs3/hal/group___p_a_l.html) is used.

View file

@ -74,6 +74,103 @@
#define A6 0x06 #define A6 0x06
#define A7 0x07 #define A7 0x07
#endif #endif
#elif defined(PROTOCOL_CHIBIOS)
#define A0 PAL_LINE(GPIOA, 0)
#define A1 PAL_LINE(GPIOA, 1)
#define A2 PAL_LINE(GPIOA, 2)
#define A3 PAL_LINE(GPIOA, 3)
#define A4 PAL_LINE(GPIOA, 4)
#define A5 PAL_LINE(GPIOA, 5)
#define A6 PAL_LINE(GPIOA, 6)
#define A7 PAL_LINE(GPIOA, 7)
#define A8 PAL_LINE(GPIOA, 8)
#define A9 PAL_LINE(GPIOA, 9)
#define A10 PAL_LINE(GPIOA, 10)
#define A11 PAL_LINE(GPIOA, 11)
#define A12 PAL_LINE(GPIOA, 12)
#define A13 PAL_LINE(GPIOA, 13)
#define A14 PAL_LINE(GPIOA, 14)
#define A15 PAL_LINE(GPIOA, 15)
#define B0 PAL_LINE(GPIOB, 0)
#define B1 PAL_LINE(GPIOB, 1)
#define B2 PAL_LINE(GPIOB, 2)
#define B3 PAL_LINE(GPIOB, 3)
#define B4 PAL_LINE(GPIOB, 4)
#define B5 PAL_LINE(GPIOB, 5)
#define B6 PAL_LINE(GPIOB, 6)
#define B7 PAL_LINE(GPIOB, 7)
#define B8 PAL_LINE(GPIOB, 8)
#define B9 PAL_LINE(GPIOB, 9)
#define B10 PAL_LINE(GPIOB, 10)
#define B11 PAL_LINE(GPIOB, 11)
#define B12 PAL_LINE(GPIOB, 12)
#define B13 PAL_LINE(GPIOB, 13)
#define B14 PAL_LINE(GPIOB, 14)
#define B15 PAL_LINE(GPIOB, 15)
#define C0 PAL_LINE(GPIOC, 0)
#define C1 PAL_LINE(GPIOC, 1)
#define C2 PAL_LINE(GPIOC, 2)
#define C3 PAL_LINE(GPIOC, 3)
#define C4 PAL_LINE(GPIOC, 4)
#define C5 PAL_LINE(GPIOC, 5)
#define C6 PAL_LINE(GPIOC, 6)
#define C7 PAL_LINE(GPIOC, 7)
#define C8 PAL_LINE(GPIOC, 8)
#define C9 PAL_LINE(GPIOC, 9)
#define C10 PAL_LINE(GPIOC, 10)
#define C11 PAL_LINE(GPIOC, 11)
#define C12 PAL_LINE(GPIOC, 12)
#define C13 PAL_LINE(GPIOC, 13)
#define C14 PAL_LINE(GPIOC, 14)
#define C15 PAL_LINE(GPIOC, 15)
#define D0 PAL_LINE(GPIOD, 0)
#define D1 PAL_LINE(GPIOD, 1)
#define D2 PAL_LINE(GPIOD, 2)
#define D3 PAL_LINE(GPIOD, 3)
#define D4 PAL_LINE(GPIOD, 4)
#define D5 PAL_LINE(GPIOD, 5)
#define D6 PAL_LINE(GPIOD, 6)
#define D7 PAL_LINE(GPIOD, 7)
#define D8 PAL_LINE(GPIOD, 8)
#define D9 PAL_LINE(GPIOD, 9)
#define D10 PAL_LINE(GPIOD, 10)
#define D11 PAL_LINE(GPIOD, 11)
#define D12 PAL_LINE(GPIOD, 12)
#define D13 PAL_LINE(GPIOD, 13)
#define D14 PAL_LINE(GPIOD, 14)
#define D15 PAL_LINE(GPIOD, 15)
#define E0 PAL_LINE(GPIOE, 0)
#define E1 PAL_LINE(GPIOE, 1)
#define E2 PAL_LINE(GPIOE, 2)
#define E3 PAL_LINE(GPIOE, 3)
#define E4 PAL_LINE(GPIOE, 4)
#define E5 PAL_LINE(GPIOE, 5)
#define E6 PAL_LINE(GPIOE, 6)
#define E7 PAL_LINE(GPIOE, 7)
#define E8 PAL_LINE(GPIOE, 8)
#define E9 PAL_LINE(GPIOE, 9)
#define E10 PAL_LINE(GPIOE, 10)
#define E11 PAL_LINE(GPIOE, 11)
#define E12 PAL_LINE(GPIOE, 12)
#define E13 PAL_LINE(GPIOE, 13)
#define E14 PAL_LINE(GPIOE, 14)
#define E15 PAL_LINE(GPIOE, 15)
#define F0 PAL_LINE(GPIOF, 0)
#define F1 PAL_LINE(GPIOF, 1)
#define F2 PAL_LINE(GPIOF, 2)
#define F3 PAL_LINE(GPIOF, 3)
#define F4 PAL_LINE(GPIOF, 4)
#define F5 PAL_LINE(GPIOF, 5)
#define F6 PAL_LINE(GPIOF, 6)
#define F7 PAL_LINE(GPIOF, 7)
#define F8 PAL_LINE(GPIOF, 8)
#define F9 PAL_LINE(GPIOF, 9)
#define F10 PAL_LINE(GPIOF, 10)
#define F11 PAL_LINE(GPIOF, 11)
#define F12 PAL_LINE(GPIOF, 12)
#define F13 PAL_LINE(GPIOF, 13)
#define F14 PAL_LINE(GPIOF, 14)
#define F15 PAL_LINE(GPIOF, 15)
#endif #endif
/* USART configuration */ /* USART configuration */

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2012-2017 Jun Wako, Jack Humbert Copyright 2012-2018 Jun Wako, Jack Humbert, Yiancar
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -16,15 +16,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#if defined(__AVR__)
#include <avr/io.h>
#endif
#include "wait.h" #include "wait.h"
#include "print.h" #include "print.h"
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
#include "matrix.h" #include "matrix.h"
#include "timer.h" #include "timer.h"
#include "quantum.h"
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
@ -60,8 +58,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif #endif
#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) #if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
#endif #endif
/* matrix state(1:on, 0:off) */ /* matrix state(1:on, 0:off) */
@ -271,9 +269,7 @@ uint8_t matrix_key_count(void)
static void init_cols(void) static void init_cols(void)
{ {
for(uint8_t x = 0; x < MATRIX_COLS; x++) { for(uint8_t x = 0; x < MATRIX_COLS; x++) {
uint8_t pin = col_pins[x]; setPinInputHigh(col_pins[x]);
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
} }
} }
@ -293,8 +289,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
// Select the col pin to read (active low) // Select the col pin to read (active low)
uint8_t pin = col_pins[col_index]; uint8_t pin_state = readPin(col_pins[col_index]);
uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
// Populate the matrix row with the state of the col pin // Populate the matrix row with the state of the col pin
current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
@ -308,24 +303,19 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
static void select_row(uint8_t row) static void select_row(uint8_t row)
{ {
uint8_t pin = row_pins[row]; setPinOutput(row_pins[row]);
_SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT writePinLow(row_pins[row]);
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
} }
static void unselect_row(uint8_t row) static void unselect_row(uint8_t row)
{ {
uint8_t pin = row_pins[row]; setPinInputHigh(row_pins[row]);
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
} }
static void unselect_rows(void) static void unselect_rows(void)
{ {
for(uint8_t x = 0; x < MATRIX_ROWS; x++) { for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
uint8_t pin = row_pins[x]; setPinInput(row_pins[x]);
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
} }
} }
@ -334,9 +324,7 @@ static void unselect_rows(void)
static void init_rows(void) static void init_rows(void)
{ {
for(uint8_t x = 0; x < MATRIX_ROWS; x++) { for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
uint8_t pin = row_pins[x]; setPinInputHigh(row_pins[x]);
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
} }
} }
@ -356,7 +344,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
matrix_row_t last_row_value = current_matrix[row_index]; matrix_row_t last_row_value = current_matrix[row_index];
// Check row pin state // Check row pin state
if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0) if (readPin(row_pins[row_index]) == 0)
{ {
// Pin LO, set col bit // Pin LO, set col bit
current_matrix[row_index] |= (ROW_SHIFTER << current_col); current_matrix[row_index] |= (ROW_SHIFTER << current_col);
@ -382,24 +370,19 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
static void select_col(uint8_t col) static void select_col(uint8_t col)
{ {
uint8_t pin = col_pins[col]; setPinOutput(col_pins[col]);
_SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT writePinLow(col_pins[col]);
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
} }
static void unselect_col(uint8_t col) static void unselect_col(uint8_t col)
{ {
uint8_t pin = col_pins[col]; setPinInputHigh(col_pins[col]);
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
} }
static void unselect_cols(void) static void unselect_cols(void)
{ {
for(uint8_t x = 0; x < MATRIX_COLS; x++) { for(uint8_t x = 0; x < MATRIX_COLS; x++) {
uint8_t pin = col_pins[x]; setPinInputHigh(col_pins[x]);
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
} }
} }

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 Erez Zukerman, Jack Humbert /* Copyright 2016-2018 Erez Zukerman, Jack Humbert, Yiancar
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -21,6 +21,9 @@
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#endif #endif
#if defined(PROTOCOL_CHIBIOS)
#include "hal.h"
#endif
#include "wait.h" #include "wait.h"
#include "matrix.h" #include "matrix.h"
#include "keymap.h" #include "keymap.h"
@ -133,6 +136,48 @@ extern uint32_t default_layer_state;
#include "hd44780.h" #include "hd44780.h"
#endif #endif
//Function substitutions to ease GPIO manipulation
#ifdef __AVR__
#define pin_t uint8_t
#define setPinInput(pin) _SFR_IO8((pin >> 4) + 1) &= ~ _BV(pin & 0xF)
#define setPinInputHigh(pin) ({\
_SFR_IO8((pin >> 4) + 1) &= ~ _BV(pin & 0xF);\
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);\
})
#define setPinInputLow(pin) _Static_assert(0, "AVR Processors cannot impliment an input as pull low")
#define setPinOutput(pin) _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF)
#define writePinHigh(pin) _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF)
#define writePinLow(pin) _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF)
static inline void writePin(pin_t pin, uint8_t level){
if (level){
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
} else {
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF);
}
}
#define readPin(pin) (_SFR_IO8(pin >> 4) & _BV(pin & 0xF))
#elif defined(PROTOCOL_CHIBIOS)
#define pin_t ioline_t
#define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT)
#define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP)
#define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN)
#define setPinOutput(pin) palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)
#define writePinHigh(pin) palSetLine(pin)
#define writePinLow(pin) palClearLine(pin)
static inline void writePin(pin_t pin, uint8_t level){
if (level){
palSetLine(pin);
} else {
palClearLine(pin);
}
}
#define readPin(pin) palReadLine(pin)
#endif
#define STRINGIZE(z) #z #define STRINGIZE(z) #z
#define ADD_SLASH_X(y) STRINGIZE(\x ## y) #define ADD_SLASH_X(y) STRINGIZE(\x ## y)
#define SYMBOL_STR(x) ADD_SLASH_X(x) #define SYMBOL_STR(x) ADD_SLASH_X(x)