Update naming convention for GPIO control macros (#23085)

This commit is contained in:
Ryan 2024-02-17 00:18:26 +11:00 committed by GitHub
parent 6890c1aeb8
commit b8646bc40b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 100 additions and 83 deletions

View file

@ -119,11 +119,11 @@ void keyboard_pre_init_user(void) {
// Call the keyboard pre init code. // Call the keyboard pre init code.
// Set our LED pins as output // Set our LED pins as output
setPinOutput(B0); gpio_set_pin_output(B0);
setPinOutput(B1); gpio_set_pin_output(B1);
setPinOutput(B2); gpio_set_pin_output(B2);
setPinOutput(B3); gpio_set_pin_output(B3);
setPinOutput(B4); gpio_set_pin_output(B4);
} }
``` ```

View file

@ -56,16 +56,16 @@ This is a template indicator function that can be implemented on keyboard level
bool led_update_kb(led_t led_state) { bool led_update_kb(led_t led_state) {
bool res = led_update_user(led_state); bool res = led_update_user(led_state);
if(res) { if(res) {
// writePin sets the pin high for 1 and low for 0. // gpio_write_pin sets the pin high for 1 and low for 0.
// In this example the pins are inverted, setting // In this example the pins are inverted, setting
// it low/0 turns it on, and high/1 turns the LED off. // it low/0 turns it on, and high/1 turns the LED off.
// This behavior depends on whether the LED is between the pin // This behavior depends on whether the LED is between the pin
// and VCC or the pin and GND. // and VCC or the pin and GND.
writePin(B0, !led_state.num_lock); gpio_write_pin(B0, !led_state.num_lock);
writePin(B1, !led_state.caps_lock); gpio_write_pin(B1, !led_state.caps_lock);
writePin(B2, !led_state.scroll_lock); gpio_write_pin(B2, !led_state.scroll_lock);
writePin(B3, !led_state.compose); gpio_write_pin(B3, !led_state.compose);
writePin(B4, !led_state.kana); gpio_write_pin(B4, !led_state.kana);
} }
return res; return res;
} }

View file

@ -2,29 +2,29 @@
QMK has a GPIO control abstraction layer which is microcontroller agnostic. This is done to allow easy access to pin control across different platforms. QMK has a GPIO control abstraction layer which is microcontroller agnostic. This is done to allow easy access to pin control across different platforms.
## Functions :id=functions ## Macros :id=macros
The following functions provide basic control of GPIOs and are found in `platforms/<platform>/gpio.h`. The following macros provide basic control of GPIOs and are found in `platforms/<platform>/gpio.h`.
| Function | Description | Old AVR Examples | Old ChibiOS/ARM Examples | |Macro |Description |
|------------------------------|-----------------------------------------------------|-------------------------------------------------|--------------------------------------------------| |-------------------------------------|---------------------------------------------------------------------|
| `setPinInput(pin)` | Set pin as input with high impedance (High-Z) | `DDRB &= ~(1<<2)` | `palSetLineMode(pin, PAL_MODE_INPUT)` | |`gpio_set_pin_input(pin)` |Set pin as input with high impedance (High-Z) |
| `setPinInputHigh(pin)` | Set pin as input with builtin pull-up resistor | `DDRB &= ~(1<<2); PORTB \|= (1<<2)` | `palSetLineMode(pin, PAL_MODE_INPUT_PULLUP)` | |`gpio_set_pin_input_high(pin)` |Set pin as input with builtin pull-up resistor |
| `setPinInputLow(pin)` | Set pin as input with builtin pull-down resistor | N/A (Not supported on AVR) | `palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN)` | |`gpio_set_pin_input_low(pin)` |Set pin as input with builtin pull-down resistor (unavailable on AVR)|
| `setPinOutput(pin)` | Set pin as output (alias of `setPinOutputPushPull`) | `DDRB \|= (1<<2)` | `palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)` | |`gpio_set_pin_output(pin)` |Set pin as output (alias of `gpio_set_pin_output_push_pull`) |
| `setPinOutputPushPull(pin)` | Set pin as output, push/pull mode | `DDRB \|= (1<<2)` | `palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)` | |`gpio_set_pin_output_push_pull(pin)` |Set pin as output, push/pull mode |
| `setPinOutputOpenDrain(pin)` | Set pin as output, open-drain mode | N/A (Not implemented on AVR) | `palSetLineMode(pin, PAL_MODE_OUTPUT_OPENDRAIN)` | |`gpio_set_pin_output_open_drain(pin)`|Set pin as output, open-drain mode (unavailable on AVR and ATSAM) |
| `writePinHigh(pin)` | Set pin level as high, assuming it is an output | `PORTB \|= (1<<2)` | `palSetLine(pin)` | |`gpio_write_pin_high(pin)` |Set pin level as high, assuming it is an output |
| `writePinLow(pin)` | Set pin level as low, assuming it is an output | `PORTB &= ~(1<<2)` | `palClearLine(pin)` | |`gpio_write_pin_low(pin)` |Set pin level as low, assuming it is an output |
| `writePin(pin, level)` | Set pin level, assuming it is an output | `(level) ? PORTB \|= (1<<2) : PORTB &= ~(1<<2)` | `(level) ? palSetLine(pin) : palClearLine(pin)` | |`gpio_write_pin(pin, level)` |Set pin level, assuming it is an output |
| `readPin(pin)` | Returns the level of the pin | `_SFR_IO8(pin >> 4) & _BV(pin & 0xF)` | `palReadLine(pin)` | |`gpio_read_pin(pin)` |Returns the level of the pin |
| `togglePin(pin)` | Invert pin level, assuming it is an output | `PORTB ^= (1<<2)` | `palToggleLine(pin)` | |`gpio_toggle_pin(pin)` |Invert pin level, assuming it is an output |
## Advanced Settings :id=advanced-settings ## Advanced Settings :id=advanced-settings
Each microcontroller can have multiple advanced settings regarding its GPIO. This abstraction layer does not limit the use of architecture-specific functions. Advanced users should consult the datasheet of their desired device and include any needed libraries. For AVR, the standard avr/io.h library is used; for STM32, the ChibiOS [PAL library](https://chibios.sourceforge.net/docs3/hal/group___p_a_l.html) is used. Each microcontroller can have multiple advanced settings regarding its GPIO. This abstraction layer does not limit the use of architecture-specific functions. Advanced users should consult the datasheet of their desired device. For AVR, the standard `avr/io.h` library is used; for STM32, the ChibiOS [PAL library](https://chibios.sourceforge.net/docs3/hal/group___p_a_l.html) is used.
## Atomic Operation ## Atomic Operation :id=atomic-operation
The above functions are not always guaranteed to work atomically. Therefore, if you want to prevent interruptions in the middle of operations when using multiple combinations of the above functions, use the following `ATOMIC_BLOCK_FORCEON` macro. The above functions are not always guaranteed to work atomically. Therefore, if you want to prevent interruptions in the middle of operations when using multiple combinations of the above functions, use the following `ATOMIC_BLOCK_FORCEON` macro.

View file

@ -127,8 +127,8 @@ This function is weakly defined, meaning it can be overridden if necessary for y
```c ```c
void i2c_init(void) { void i2c_init(void) {
setPinInput(B6); // Try releasing special pins for a short time gpio_set_pin_input(B6); // Try releasing special pins for a short time
setPinInput(B7); gpio_set_pin_input(B7);
wait_ms(10); // Wait for the release to happen wait_ms(10); // Wait for the release to happen
palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B6 to I2C function palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B6 to I2C function

View file

@ -15,7 +15,7 @@
*/ */
#pragma once #pragma once
#include "stdint.h" #include <stdint.h>
#include "samd51j18a.h" #include "samd51j18a.h"
#include "pin_defs.h" #include "pin_defs.h"
@ -26,13 +26,13 @@ typedef uint8_t pin_t;
#define SAMD_PIN(pin) ((pin)&0x1f) #define SAMD_PIN(pin) ((pin)&0x1f)
#define SAMD_PIN_MASK(pin) (1 << ((pin)&0x1f)) #define SAMD_PIN_MASK(pin) (1 << ((pin)&0x1f))
#define setPinInput(pin) \ #define gpio_set_pin_input(pin) \
do { \ do { \
PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \ PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \
PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
} while (0) } while (0)
#define setPinInputHigh(pin) \ #define gpio_set_pin_input_high(pin) \
do { \ do { \
PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
@ -40,7 +40,7 @@ typedef uint8_t pin_t;
PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \ PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \
} while (0) } while (0)
#define setPinInputLow(pin) \ #define gpio_set_pin_input_low(pin) \
do { \ do { \
PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
@ -48,27 +48,27 @@ typedef uint8_t pin_t;
PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \ PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \
} while (0) } while (0)
#define setPinOutputPushPull(pin) \ #define gpio_set_pin_output_push_pull(pin) \
do { \ do { \
PORT->Group[SAMD_PORT(pin)].DIRSET.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].DIRSET.reg = SAMD_PIN_MASK(pin); \
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
} while (0) } while (0)
#define setPinOutputOpenDrain(pin) _Static_assert(0, "arm_atsam platform does not implement an open-drain output") #define gpio_set_pin_output_open_drain(pin) _Static_assert(0, "Open-drain outputs are not available on ATSAM")
#define setPinOutput(pin) setPinOutputPushPull(pin) #define gpio_set_pin_output(pin) gpio_set_pin_output_push_pull(pin)
#define writePinHigh(pin) \ #define gpio_write_pin_high(pin) \
do { \ do { \
PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
} while (0) } while (0)
#define writePinLow(pin) \ #define gpio_write_pin_low(pin) \
do { \ do { \
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
} while (0) } while (0)
#define writePin(pin, level) \ #define gpio_write_pin(pin, level) \
do { \ do { \
if (level) \ if (level) \
PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
@ -76,6 +76,6 @@ typedef uint8_t pin_t;
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
} while (0) } while (0)
#define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0) #define gpio_read_pin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0)
#define togglePin(pin) (PORT->Group[SAMD_PORT(pin)].OUTTGL.reg = SAMD_PIN_MASK(pin)) #define gpio_toggle_pin(pin) (PORT->Group[SAMD_PORT(pin)].OUTTGL.reg = SAMD_PIN_MASK(pin))

View file

@ -22,17 +22,17 @@ typedef uint8_t pin_t;
/* Operation of GPIO by pin. */ /* Operation of GPIO by pin. */
#define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) #define gpio_set_pin_input(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
#define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) #define gpio_set_pin_input_high(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
#define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low") #define gpio_set_pin_input_low(pin) _Static_assert(0, "GPIO pulldowns in input mode are not available on AVR")
#define setPinOutputPushPull(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) #define gpio_set_pin_output_push_pull(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
#define setPinOutputOpenDrain(pin) _Static_assert(0, "AVR platform does not implement an open-drain output") #define gpio_set_pin_output_open_drain(pin) _Static_assert(0, "Open-drain outputs are not available on AVR")
#define setPinOutput(pin) setPinOutputPushPull(pin) #define gpio_set_pin_output(pin) gpio_set_pin_output_push_pull(pin)
#define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) #define gpio_write_pin_high(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
#define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) #define gpio_write_pin_low(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
#define writePin(pin, level) ((level) ? writePinHigh(pin) : writePinLow(pin)) #define gpio_write_pin(pin, level) ((level) ? gpio_write_pin_high(pin) : gpio_write_pin_low(pin))
#define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) #define gpio_read_pin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
#define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF)) #define gpio_toggle_pin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF))

View file

@ -22,24 +22,24 @@ typedef ioline_t pin_t;
/* Operation of GPIO by pin. */ /* Operation of GPIO by pin. */
#define setPinInput(pin) palSetLineMode((pin), PAL_MODE_INPUT) #define gpio_set_pin_input(pin) palSetLineMode((pin), PAL_MODE_INPUT)
#define setPinInputHigh(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLUP) #define gpio_set_pin_input_high(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLUP)
#define setPinInputLow(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLDOWN) #define gpio_set_pin_input_low(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLDOWN)
#define setPinOutputPushPull(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_PUSHPULL) #define gpio_set_pin_output_push_pull(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_PUSHPULL)
#define setPinOutputOpenDrain(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_OPENDRAIN) #define gpio_set_pin_output_open_drain(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_OPENDRAIN)
#define setPinOutput(pin) setPinOutputPushPull(pin) #define gpio_set_pin_output(pin) gpio_set_pin_output_push_pull(pin)
#define writePinHigh(pin) palSetLine(pin) #define gpio_write_pin_high(pin) palSetLine(pin)
#define writePinLow(pin) palClearLine(pin) #define gpio_write_pin_low(pin) palClearLine(pin)
#define writePin(pin, level) \ #define gpio_write_pin(pin, level) \
do { \ do { \
if (level) { \ if (level) { \
writePinHigh(pin); \ gpio_write_pin_high(pin); \
} else { \ } else { \
writePinLow(pin); \ gpio_write_pin_low(pin); \
} \ } \
} while (0) } while (0)
#define readPin(pin) palReadLine(pin) #define gpio_read_pin(pin) palReadLine(pin)
#define togglePin(pin) palToggleLine(pin) #define gpio_toggle_pin(pin) palToggleLine(pin)

View file

@ -19,4 +19,21 @@
#if __has_include_next("gpio.h") #if __has_include_next("gpio.h")
# include_next "gpio.h" /* Include the platforms gpio.h */ # include_next "gpio.h" /* Include the platforms gpio.h */
#endif #endif
// ======== DEPRECATED DEFINES - DO NOT USE ========
#define setPinInput(pin) gpio_set_pin_input(pin)
#define setPinInputHigh(pin) gpio_set_pin_input_high(pin)
#define setPinInputLow(pin) gpio_set_pin_input_low(pin)
#define setPinOutputPushPull(pin) gpio_set_pin_output_push_pull(pin)
#define setPinOutputOpenDrain(pin) gpio_set_pin_output_open_drain(pin)
#define setPinOutput(pin) gpio_set_pin_output_push_pull(pin)
#define writePinHigh(pin) gpio_write_pin_high(pin)
#define writePinLow(pin) gpio_write_pin_low(pin)
#define writePin(pin, level) gpio_write_pin(pin, level)
#define readPin(pin) gpio_read_pin(pin)
#define togglePin(pin) gpio_toggle_pin(pin)

View file

@ -19,14 +19,14 @@
bool pins[32] = {0}; bool pins[32] = {0};
bool pinIsInputHigh[32] = {0}; bool pinIsInputHigh[32] = {0};
uint8_t mockSetPinInputHigh(pin_t pin) { uint8_t mock_set_pin_input_high(pin_t pin) {
// dprintf("Setting pin %d input high.", pin); // dprintf("Setting pin %d input high.", pin);
pins[pin] = true; pins[pin] = true;
pinIsInputHigh[pin] = true; pinIsInputHigh[pin] = true;
return 0; return 0;
} }
bool mockReadPin(pin_t pin) { bool mock_read_pin(pin_t pin) {
return pins[pin]; return pins[pin];
} }

View file

@ -24,11 +24,11 @@ typedef uint8_t pin_t;
extern bool pins[]; extern bool pins[];
extern bool pinIsInputHigh[]; extern bool pinIsInputHigh[];
#define setPinInputHigh(pin) (mockSetPinInputHigh(pin)) #define gpio_set_pin_input_high(pin) (mock_set_pin_input_high(pin))
#define readPin(pin) (mockReadPin(pin)) #define gpio_read_pin(pin) (mock_read_pin(pin))
uint8_t mockSetPinInputHigh(pin_t pin); uint8_t mock_set_pin_input_high(pin_t pin);
bool mockReadPin(pin_t pin); bool mock_read_pin(pin_t pin);
bool setPin(pin_t pin, bool val); bool setPin(pin_t pin, bool val);

View file

@ -19,14 +19,14 @@
bool pins[32] = {0}; bool pins[32] = {0};
bool pinIsInputHigh[32] = {0}; bool pinIsInputHigh[32] = {0};
uint8_t mockSetPinInputHigh(pin_t pin) { uint8_t mock_set_pin_input_high(pin_t pin) {
// dprintf("Setting pin %d input high.", pin); // dprintf("Setting pin %d input high.", pin);
pins[pin] = true; pins[pin] = true;
pinIsInputHigh[pin] = true; pinIsInputHigh[pin] = true;
return 0; return 0;
} }
bool mockReadPin(pin_t pin) { bool mock_read_pin(pin_t pin) {
return pins[pin]; return pins[pin];
} }

View file

@ -28,11 +28,11 @@ void encoder_update_raw(uint8_t* slave_state);
extern bool pins[]; extern bool pins[];
extern bool pinIsInputHigh[]; extern bool pinIsInputHigh[];
#define setPinInputHigh(pin) (mockSetPinInputHigh(pin)) #define gpio_set_pin_input_high(pin) (mock_set_pin_input_high(pin))
#define readPin(pin) (mockReadPin(pin)) #define gpio_read_pin(pin) (mock_read_pin(pin))
uint8_t mockSetPinInputHigh(pin_t pin); uint8_t mock_set_pin_input_high(pin_t pin);
bool mockReadPin(pin_t pin); bool mock_read_pin(pin_t pin);
bool setPin(pin_t pin, bool val); bool setPin(pin_t pin, bool val);