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:
		
							parent
							
								
									fa47f5fb15
								
							
						
					
					
						commit
						7fe03d085c
					
				
							
								
								
									
										23
									
								
								docs/internals_gpio_control.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								docs/internals_gpio_control.md
									
									
									
									
									
										Normal 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.
 | 
			
		||||
 | 
			
		||||
@ -74,6 +74,103 @@
 | 
			
		||||
        #define A6 0x06
 | 
			
		||||
        #define A7 0x07
 | 
			
		||||
    #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
 | 
			
		||||
 | 
			
		||||
/* USART configuration */
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
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 <stdbool.h>
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
#include <avr/io.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "matrix.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "quantum.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Set 0 if debouncing isn't needed */
 | 
			
		||||
@ -60,8 +58,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
 | 
			
		||||
static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
 | 
			
		||||
static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
 | 
			
		||||
static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
 | 
			
		||||
static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* matrix state(1:on, 0:off) */
 | 
			
		||||
@ -271,9 +269,7 @@ uint8_t matrix_key_count(void)
 | 
			
		||||
static void init_cols(void)
 | 
			
		||||
{
 | 
			
		||||
    for(uint8_t x = 0; x < MATRIX_COLS; x++) {
 | 
			
		||||
        uint8_t pin = col_pins[x];
 | 
			
		||||
        _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
 | 
			
		||||
        _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
 | 
			
		||||
        setPinInputHigh(col_pins[x]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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++) {
 | 
			
		||||
 | 
			
		||||
        // Select the col pin to read (active low)
 | 
			
		||||
        uint8_t pin = col_pins[col_index];
 | 
			
		||||
        uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
 | 
			
		||||
        uint8_t pin_state = readPin(col_pins[col_index]);
 | 
			
		||||
 | 
			
		||||
        // Populate the matrix row with the state of the col pin
 | 
			
		||||
        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)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t pin = row_pins[row];
 | 
			
		||||
    _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
 | 
			
		||||
    _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
 | 
			
		||||
    setPinOutput(row_pins[row]);
 | 
			
		||||
    writePinLow(row_pins[row]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void unselect_row(uint8_t row)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t pin = row_pins[row];
 | 
			
		||||
    _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
 | 
			
		||||
    _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
 | 
			
		||||
    setPinInputHigh(row_pins[row]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void unselect_rows(void)
 | 
			
		||||
{
 | 
			
		||||
    for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
 | 
			
		||||
        uint8_t pin = row_pins[x];
 | 
			
		||||
        _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
 | 
			
		||||
        _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
 | 
			
		||||
        setPinInput(row_pins[x]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -334,9 +324,7 @@ static void unselect_rows(void)
 | 
			
		||||
static void init_rows(void)
 | 
			
		||||
{
 | 
			
		||||
    for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
 | 
			
		||||
        uint8_t pin = row_pins[x];
 | 
			
		||||
        _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
 | 
			
		||||
        _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
 | 
			
		||||
        setPinInputHigh(row_pins[x]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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];
 | 
			
		||||
 | 
			
		||||
        // 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
 | 
			
		||||
            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)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t pin = col_pins[col];
 | 
			
		||||
    _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
 | 
			
		||||
    _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
 | 
			
		||||
    setPinOutput(col_pins[col]);
 | 
			
		||||
    writePinLow(col_pins[col]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void unselect_col(uint8_t col)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t pin = col_pins[col];
 | 
			
		||||
    _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
 | 
			
		||||
    _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
 | 
			
		||||
    setPinInputHigh(col_pins[col]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void unselect_cols(void)
 | 
			
		||||
{
 | 
			
		||||
    for(uint8_t x = 0; x < MATRIX_COLS; x++) {
 | 
			
		||||
        uint8_t pin = col_pins[x];
 | 
			
		||||
        _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
 | 
			
		||||
        _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
 | 
			
		||||
        setPinInputHigh(col_pins[x]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
@ -17,9 +17,12 @@
 | 
			
		||||
#define QUANTUM_H
 | 
			
		||||
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
#include <avr/pgmspace.h>
 | 
			
		||||
#include <avr/io.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
    #include <avr/pgmspace.h>
 | 
			
		||||
    #include <avr/io.h>
 | 
			
		||||
    #include <avr/interrupt.h>
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(PROTOCOL_CHIBIOS)
 | 
			
		||||
    #include "hal.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
#include "matrix.h"
 | 
			
		||||
@ -133,6 +136,48 @@ extern uint32_t default_layer_state;
 | 
			
		||||
    #include "hd44780.h"
 | 
			
		||||
#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 ADD_SLASH_X(y) STRINGIZE(\x ## y)
 | 
			
		||||
#define SYMBOL_STR(x) ADD_SLASH_X(x)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user