diff options
Diffstat (limited to 'quantum/split_common')
-rw-r--r-- | quantum/split_common/matrix.c | 328 | ||||
-rw-r--r-- | quantum/split_common/post_config.h | 28 | ||||
-rw-r--r-- | quantum/split_common/serial.c | 748 | ||||
-rw-r--r-- | quantum/split_common/serial.h | 18 | ||||
-rw-r--r-- | quantum/split_common/split_util.c | 119 | ||||
-rw-r--r-- | quantum/split_common/split_util.h | 3 | ||||
-rw-r--r-- | quantum/split_common/transport.c | 272 |
7 files changed, 749 insertions, 767 deletions
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 3c3daf3d3b..7176d0cc4f 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -30,24 +30,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "transport.h" #ifdef ENCODER_ENABLE - #include "encoder.h" +# include "encoder.h" #endif #if (MATRIX_COLS <= 8) -# define print_matrix_header() print("\nr/c 01234567\n") -# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop(matrix[i]) -# define ROW_SHIFTER ((uint8_t)1) +# define print_matrix_header() print("\nr/c 01234567\n") +# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) +# define matrix_bitpop(i) bitpop(matrix[i]) +# define ROW_SHIFTER ((uint8_t)1) #elif (MATRIX_COLS <= 16) -# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") -# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop16(matrix[i]) -# define ROW_SHIFTER ((uint16_t)1) +# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") +# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) +# define matrix_bitpop(i) bitpop16(matrix[i]) +# define ROW_SHIFTER ((uint16_t)1) #elif (MATRIX_COLS <= 32) -# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") -# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop32(matrix[i]) -# define ROW_SHIFTER ((uint32_t)1) +# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") +# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) +# define matrix_bitpop(i) bitpop32(matrix[i]) +# define ROW_SHIFTER ((uint32_t)1) #endif #define ERROR_DISCONNECT_COUNT 5 @@ -87,8 +87,8 @@ inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } inline uint8_t matrix_cols(void) { return MATRIX_COLS; } bool matrix_is_modified(void) { - if (debounce_active()) return false; - return true; + if (debounce_active()) return false; + return true; } inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } @@ -96,22 +96,22 @@ inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((mat inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } void matrix_print(void) { - print_matrix_header(); - - for (uint8_t row = 0; row < MATRIX_ROWS; row++) { - phex(row); - print(": "); - print_matrix_row(row); - print("\n"); - } + print_matrix_header(); + + for (uint8_t row = 0; row < MATRIX_ROWS; row++) { + phex(row); + print(": "); + print_matrix_row(row); + print("\n"); + } } uint8_t matrix_key_count(void) { - uint8_t count = 0; - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - count += matrix_bitpop(i); - } - return count; + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += matrix_bitpop(i); + } + return count; } // matrix code @@ -119,216 +119,222 @@ uint8_t matrix_key_count(void) { #ifdef DIRECT_PINS static void init_pins(void) { - for (int row = 0; row < MATRIX_ROWS; row++) { - for (int col = 0; col < MATRIX_COLS; col++) { - pin_t pin = direct_pins[row][col]; - if (pin != NO_PIN) { - setPinInputHigh(pin); - } + for (int row = 0; row < MATRIX_ROWS; row++) { + for (int col = 0; col < MATRIX_COLS; col++) { + pin_t pin = direct_pins[row][col]; + if (pin != NO_PIN) { + setPinInputHigh(pin); + } + } } - } } static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { - matrix_row_t last_row_value = current_matrix[current_row]; - current_matrix[current_row] = 0; + matrix_row_t last_row_value = current_matrix[current_row]; + current_matrix[current_row] = 0; - for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { - pin_t pin = direct_pins[current_row][col_index]; - if (pin != NO_PIN) { - current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index); + for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { + pin_t pin = direct_pins[current_row][col_index]; + if (pin != NO_PIN) { + current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index); + } } - } - return (last_row_value != current_matrix[current_row]); + return (last_row_value != current_matrix[current_row]); } #elif (DIODE_DIRECTION == COL2ROW) static void select_row(uint8_t row) { - setPinOutput(row_pins[row]); - writePinLow(row_pins[row]); + setPinOutput(row_pins[row]); + writePinLow(row_pins[row]); } static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); } static void unselect_rows(void) { - for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { - setPinInputHigh(row_pins[x]); - } + for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { + setPinInputHigh(row_pins[x]); + } } static void init_pins(void) { - unselect_rows(); - for (uint8_t x = 0; x < MATRIX_COLS; x++) { - setPinInputHigh(col_pins[x]); - } + unselect_rows(); + for (uint8_t x = 0; x < MATRIX_COLS; x++) { + setPinInputHigh(col_pins[x]); + } } static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { - // Store last value of row prior to reading - matrix_row_t last_row_value = current_matrix[current_row]; + // Store last value of row prior to reading + matrix_row_t last_row_value = current_matrix[current_row]; - // Clear data in matrix row - current_matrix[current_row] = 0; + // Clear data in matrix row + current_matrix[current_row] = 0; - // Select row and wait for row selecton to stabilize - select_row(current_row); - wait_us(30); + // Select row and wait for row selecton to stabilize + select_row(current_row); + wait_us(30); - // For each col... - for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { - // Populate the matrix row with the state of the col pin - current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index); - } + // For each col... + for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { + // Populate the matrix row with the state of the col pin + current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index); + } - // Unselect row - unselect_row(current_row); + // Unselect row + unselect_row(current_row); - return (last_row_value != current_matrix[current_row]); + return (last_row_value != current_matrix[current_row]); } #elif (DIODE_DIRECTION == ROW2COL) static void select_col(uint8_t col) { - setPinOutput(col_pins[col]); - writePinLow(col_pins[col]); + setPinOutput(col_pins[col]); + writePinLow(col_pins[col]); } static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); } static void unselect_cols(void) { - for (uint8_t x = 0; x < MATRIX_COLS; x++) { - setPinInputHigh(col_pins[x]); - } + for (uint8_t x = 0; x < MATRIX_COLS; x++) { + setPinInputHigh(col_pins[x]); + } } static void init_pins(void) { - unselect_cols(); - for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { - setPinInputHigh(row_pins[x]); - } + unselect_cols(); + for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { + setPinInputHigh(row_pins[x]); + } } static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { - bool matrix_changed = false; - - // Select col and wait for col selecton to stabilize - select_col(current_col); - wait_us(30); - - // For each row... - for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { - // Store last value of row prior to reading - matrix_row_t last_row_value = current_matrix[row_index]; - - // Check row pin state - if (readPin(row_pins[row_index])) { - // Pin HI, clear col bit - current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); - } else { - // Pin LO, set col bit - current_matrix[row_index] |= (ROW_SHIFTER << current_col); - } + bool matrix_changed = false; + + // Select col and wait for col selecton to stabilize + select_col(current_col); + wait_us(30); + + // For each row... + for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { + // Store last value of row prior to reading + matrix_row_t last_row_value = current_matrix[row_index]; + + // Check row pin state + if (readPin(row_pins[row_index])) { + // Pin HI, clear col bit + current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); + } else { + // Pin LO, set col bit + current_matrix[row_index] |= (ROW_SHIFTER << current_col); + } - // Determine if the matrix changed state - if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) { - matrix_changed = true; + // Determine if the matrix changed state + if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) { + matrix_changed = true; + } } - } - // Unselect col - unselect_col(current_col); + // Unselect col + unselect_col(current_col); - return matrix_changed; + return matrix_changed; } #endif void matrix_init(void) { - debug_enable = true; - debug_matrix = true; - debug_mouse = true; - - // Set pinout for right half if pinout for that half is defined - if (!isLeftHand) { + keyboard_split_setup(); + + // Set pinout for right half if pinout for that half is defined + if (!isLeftHand) { +#ifdef DIRECT_PINS_RIGHT + const pin_t direct_pins_right[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS_RIGHT; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + for (uint8_t j = 0; j < MATRIX_COLS; j++) { + direct_pins[i][j] = direct_pins_right[i][j]; + } + } +#endif #ifdef MATRIX_ROW_PINS_RIGHT - const uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT; - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - row_pins[i] = row_pins_right[i]; - } + const pin_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + row_pins[i] = row_pins_right[i]; + } #endif #ifdef MATRIX_COL_PINS_RIGHT - const uint8_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT; - for (uint8_t i = 0; i < MATRIX_COLS; i++) { - col_pins[i] = col_pins_right[i]; - } + const pin_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT; + for (uint8_t i = 0; i < MATRIX_COLS; i++) { + col_pins[i] = col_pins_right[i]; + } #endif - } + } - thisHand = isLeftHand ? 0 : (ROWS_PER_HAND); - thatHand = ROWS_PER_HAND - thisHand; + thisHand = isLeftHand ? 0 : (ROWS_PER_HAND); + thatHand = ROWS_PER_HAND - thisHand; - // initialize key pins - init_pins(); + // initialize key pins + init_pins(); - // initialize matrix state: all keys off - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - matrix[i] = 0; - } + // initialize matrix state: all keys off + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + matrix[i] = 0; + } - debounce_init(ROWS_PER_HAND); + debounce_init(ROWS_PER_HAND); - matrix_init_quantum(); + matrix_init_quantum(); } uint8_t _matrix_scan(void) { - bool changed = false; + bool changed = false; #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) - // Set row, read cols - for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { - changed |= read_cols_on_row(raw_matrix, current_row); - } + // Set row, read cols + for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; 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); - } + // 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 + thisHand, ROWS_PER_HAND, changed); + debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); - return (uint8_t)changed; + return (uint8_t)changed; } 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; + 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; } - } - } else { - error_count = 0; - } - matrix_scan_quantum(); - } else { - transport_slave(matrix + thisHand); + matrix_scan_quantum(); + } else { + transport_slave(matrix + thisHand); #ifdef ENCODER_ENABLE - encoder_read(); + encoder_read(); #endif - matrix_slave_scan_user(); - } + matrix_slave_scan_user(); + } - return ret; + return ret; } diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h index ff0fc5e193..5c0b414fb3 100644 --- a/quantum/split_common/post_config.h +++ b/quantum/split_common/post_config.h @@ -1,19 +1,19 @@ #if defined(USE_I2C) || defined(EH) - // When using I2C, using rgblight implicitly involves split support. - #if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_SPLIT) - #define RGBLIGHT_SPLIT - #endif +// When using I2C, using rgblight implicitly involves split support. +# if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_SPLIT) +# define RGBLIGHT_SPLIT +# endif - #ifndef F_SCL - #define F_SCL 100000UL // SCL frequency - #endif +# ifndef F_SCL +# define F_SCL 100000UL // SCL frequency +# endif #else // use serial - // When using serial, the user must define RGBLIGHT_SPLIT explicitly - // in config.h as needed. - // see quantum/rgblight_post_config.h - #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - // When using serial and RGBLIGHT_SPLIT need separate transaction - #define SERIAL_USE_MULTI_TRANSACTION - #endif +// When using serial, the user must define RGBLIGHT_SPLIT explicitly +// in config.h as needed. +// see quantum/rgblight_post_config.h +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) +// When using serial and RGBLIGHT_SPLIT need separate transaction +# define SERIAL_USE_MULTI_TRANSACTION +# endif #endif diff --git a/quantum/split_common/serial.c b/quantum/split_common/serial.c index 1315377a34..c27cbfdd0a 100644 --- a/quantum/split_common/serial.c +++ b/quantum/split_common/serial.c @@ -8,7 +8,7 @@ */ #ifndef F_CPU -#define F_CPU 16000000 +# define F_CPU 16000000 #endif #include <avr/io.h> @@ -17,261 +17,227 @@ #include <stddef.h> #include <stdbool.h> #include "serial.h" -//#include <pro_micro.h> #ifdef SOFT_SERIAL_PIN -#ifdef __AVR_ATmega32U4__ - // if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial. - #ifdef USE_AVR_I2C - #if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1 - #error Using ATmega32U4 I2C, so can not use PD0, PD1 - #endif - #endif - - #if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3 - #define SERIAL_PIN_DDR DDRD - #define SERIAL_PIN_PORT PORTD - #define SERIAL_PIN_INPUT PIND - #if SOFT_SERIAL_PIN == D0 - #define SERIAL_PIN_MASK _BV(PD0) - #define EIMSK_BIT _BV(INT0) - #define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01))) - #define SERIAL_PIN_INTERRUPT INT0_vect - #elif SOFT_SERIAL_PIN == D1 - #define SERIAL_PIN_MASK _BV(PD1) - #define EIMSK_BIT _BV(INT1) - #define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11))) - #define SERIAL_PIN_INTERRUPT INT1_vect - #elif SOFT_SERIAL_PIN == D2 - #define SERIAL_PIN_MASK _BV(PD2) - #define EIMSK_BIT _BV(INT2) - #define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21))) - #define SERIAL_PIN_INTERRUPT INT2_vect - #elif SOFT_SERIAL_PIN == D3 - #define SERIAL_PIN_MASK _BV(PD3) - #define EIMSK_BIT _BV(INT3) - #define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31))) - #define SERIAL_PIN_INTERRUPT INT3_vect - #endif - #elif SOFT_SERIAL_PIN == E6 - #define SERIAL_PIN_DDR DDRE - #define SERIAL_PIN_PORT PORTE - #define SERIAL_PIN_INPUT PINE - #define SERIAL_PIN_MASK _BV(PE6) - #define EIMSK_BIT _BV(INT6) - #define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) - #define SERIAL_PIN_INTERRUPT INT6_vect - #else - #error invalid SOFT_SERIAL_PIN value - #endif - -#else - #error serial.c now support ATmega32U4 only -#endif - -#define ALWAYS_INLINE __attribute__((always_inline)) -#define NO_INLINE __attribute__((noinline)) -#define _delay_sub_us(x) __builtin_avr_delay_cycles(x) +# ifdef __AVR_ATmega32U4__ +// if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial. +# ifdef USE_AVR_I2C +# if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1 +# error Using ATmega32U4 I2C, so can not use PD0, PD1 +# endif +# endif + +# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) +# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) + +# if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3 +# if SOFT_SERIAL_PIN == D0 +# define EIMSK_BIT _BV(INT0) +# define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01))) +# define SERIAL_PIN_INTERRUPT INT0_vect +# elif SOFT_SERIAL_PIN == D1 +# define EIMSK_BIT _BV(INT1) +# define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11))) +# define SERIAL_PIN_INTERRUPT INT1_vect +# elif SOFT_SERIAL_PIN == D2 +# define EIMSK_BIT _BV(INT2) +# define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21))) +# define SERIAL_PIN_INTERRUPT INT2_vect +# elif SOFT_SERIAL_PIN == D3 +# define EIMSK_BIT _BV(INT3) +# define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31))) +# define SERIAL_PIN_INTERRUPT INT3_vect +# endif +# elif SOFT_SERIAL_PIN == E6 +# define EIMSK_BIT _BV(INT6) +# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) +# define SERIAL_PIN_INTERRUPT INT6_vect +# else +# error invalid SOFT_SERIAL_PIN value +# endif + +# else +# error serial.c now support ATmega32U4 only +# endif + +# define ALWAYS_INLINE __attribute__((always_inline)) +# define NO_INLINE __attribute__((noinline)) +# define _delay_sub_us(x) __builtin_avr_delay_cycles(x) // parity check -#define ODD_PARITY 1 -#define EVEN_PARITY 0 -#define PARITY EVEN_PARITY - -#ifdef SERIAL_DELAY - // custom setup in config.h - // #define TID_SEND_ADJUST 2 - // #define SERIAL_DELAY 6 // micro sec - // #define READ_WRITE_START_ADJUST 30 // cycles - // #define READ_WRITE_WIDTH_ADJUST 8 // cycles -#else +# define ODD_PARITY 1 +# define EVEN_PARITY 0 +# define PARITY EVEN_PARITY + +# ifdef SERIAL_DELAY +// custom setup in config.h +// #define TID_SEND_ADJUST 2 +// #define SERIAL_DELAY 6 // micro sec +// #define READ_WRITE_START_ADJUST 30 // cycles +// #define READ_WRITE_WIDTH_ADJUST 8 // cycles +# else // ============ Standard setups ============ -#ifndef SELECT_SOFT_SERIAL_SPEED -#define SELECT_SOFT_SERIAL_SPEED 1 +# ifndef SELECT_SOFT_SERIAL_SPEED +# define SELECT_SOFT_SERIAL_SPEED 1 // 0: about 189kbps (Experimental only) // 1: about 137kbps (default) // 2: about 75kbps // 3: about 39kbps // 4: about 26kbps // 5: about 20kbps -#endif - -#if __GNUC__ < 6 - #define TID_SEND_ADJUST 14 -#else - #define TID_SEND_ADJUST 2 -#endif - -#if SELECT_SOFT_SERIAL_SPEED == 0 - // Very High speed - #define SERIAL_DELAY 4 // micro sec - #if __GNUC__ < 6 - #define READ_WRITE_START_ADJUST 33 // cycles - #define READ_WRITE_WIDTH_ADJUST 3 // cycles - #else - #define READ_WRITE_START_ADJUST 34 // cycles - #define READ_WRITE_WIDTH_ADJUST 7 // cycles - #endif -#elif SELECT_SOFT_SERIAL_SPEED == 1 - // High speed - #define SERIAL_DELAY 6 // micro sec - #if __GNUC__ < 6 - #define READ_WRITE_START_ADJUST 30 // cycles - #define READ_WRITE_WIDTH_ADJUST 3 // cycles - #else - #define READ_WRITE_START_ADJUST 33 // cycles - #define READ_WRITE_WIDTH_ADJUST 7 // cycles - #endif -#elif SELECT_SOFT_SERIAL_SPEED == 2 - // Middle speed - #define SERIAL_DELAY 12 // micro sec - #define READ_WRITE_START_ADJUST 30 // cycles - #if __GNUC__ < 6 - #define READ_WRITE_WIDTH_ADJUST 3 // cycles - #else - #define READ_WRITE_WIDTH_ADJUST 7 // cycles - #endif -#elif SELECT_SOFT_SERIAL_SPEED == 3 - // Low speed - #define SERIAL_DELAY 24 // micro sec - #define READ_WRITE_START_ADJUST 30 // cycles - #if __GNUC__ < 6 - #define READ_WRITE_WIDTH_ADJUST 3 // cycles - #else - #define READ_WRITE_WIDTH_ADJUST 7 // cycles - #endif -#elif SELECT_SOFT_SERIAL_SPEED == 4 - // Very Low speed - #define SERIAL_DELAY 36 // micro sec - #define READ_WRITE_START_ADJUST 30 // cycles - #if __GNUC__ < 6 - #define READ_WRITE_WIDTH_ADJUST 3 // cycles - #else - #define READ_WRITE_WIDTH_ADJUST 7 // cycles - #endif -#elif SELECT_SOFT_SERIAL_SPEED == 5 - // Ultra Low speed - #define SERIAL_DELAY 48 // micro sec - #define READ_WRITE_START_ADJUST 30 // cycles - #if __GNUC__ < 6 - #define READ_WRITE_WIDTH_ADJUST 3 // cycles - #else - #define READ_WRITE_WIDTH_ADJUST 7 // cycles - #endif -#else -#error invalid SELECT_SOFT_SERIAL_SPEED value -#endif /* SELECT_SOFT_SERIAL_SPEED */ -#endif /* SERIAL_DELAY */ - -#define SERIAL_DELAY_HALF1 (SERIAL_DELAY/2) -#define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY/2) - -#define SLAVE_INT_WIDTH_US 1 -#ifndef SERIAL_USE_MULTI_TRANSACTION - #define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY -#else - #define SLAVE_INT_ACK_WIDTH_UNIT 2 - #define SLAVE_INT_ACK_WIDTH 4 -#endif - -static SSTD_t *Transaction_table = NULL; +# endif + +# if __GNUC__ < 6 +# define TID_SEND_ADJUST 14 +# else +# define TID_SEND_ADJUST 2 +# endif + +# if SELECT_SOFT_SERIAL_SPEED == 0 +// Very High speed +# define SERIAL_DELAY 4 // micro sec +# if __GNUC__ < 6 +# define READ_WRITE_START_ADJUST 33 // cycles +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_START_ADJUST 34 // cycles +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 1 +// High speed +# define SERIAL_DELAY 6 // micro sec +# if __GNUC__ < 6 +# define READ_WRITE_START_ADJUST 30 // cycles +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_START_ADJUST 33 // cycles +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 2 +// Middle speed +# define SERIAL_DELAY 12 // micro sec +# define READ_WRITE_START_ADJUST 30 // cycles +# if __GNUC__ < 6 +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 3 +// Low speed +# define SERIAL_DELAY 24 // micro sec +# define READ_WRITE_START_ADJUST 30 // cycles +# if __GNUC__ < 6 +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 4 +// Very Low speed +# define SERIAL_DELAY 36 // micro sec +# define READ_WRITE_START_ADJUST 30 // cycles +# if __GNUC__ < 6 +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 5 +// Ultra Low speed +# define SERIAL_DELAY 48 // micro sec +# define READ_WRITE_START_ADJUST 30 // cycles +# if __GNUC__ < 6 +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# else +# error invalid SELECT_SOFT_SERIAL_SPEED value +# endif /* SELECT_SOFT_SERIAL_SPEED */ +# endif /* SERIAL_DELAY */ + +# define SERIAL_DELAY_HALF1 (SERIAL_DELAY / 2) +# define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2) + +# define SLAVE_INT_WIDTH_US 1 +# ifndef SERIAL_USE_MULTI_TRANSACTION +# define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY +# else +# define SLAVE_INT_ACK_WIDTH_UNIT 2 +# define SLAVE_INT_ACK_WIDTH 4 +# endif + +static SSTD_t *Transaction_table = NULL; static uint8_t Transaction_table_size = 0; inline static void serial_delay(void) ALWAYS_INLINE; -inline static -void serial_delay(void) { - _delay_us(SERIAL_DELAY); -} +inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); } inline static void serial_delay_half1(void) ALWAYS_INLINE; -inline static -void serial_delay_half1(void) { - _delay_us(SERIAL_DELAY_HALF1); -} +inline static void serial_delay_half1(void) { _delay_us(SERIAL_DELAY_HALF1); } inline static void serial_delay_half2(void) ALWAYS_INLINE; -inline static -void serial_delay_half2(void) { - _delay_us(SERIAL_DELAY_HALF2); -} +inline static void serial_delay_half2(void) { _delay_us(SERIAL_DELAY_HALF2); } inline static void serial_output(void) ALWAYS_INLINE; -inline static -void serial_output(void) { - SERIAL_PIN_DDR |= SERIAL_PIN_MASK; -} +inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); } // make the serial pin an input with pull-up resistor inline static void serial_input_with_pullup(void) ALWAYS_INLINE; -inline static -void serial_input_with_pullup(void) { - SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK; - SERIAL_PIN_PORT |= SERIAL_PIN_MASK; -} +inline static void serial_input_with_pullup(void) { setPinInputHigh(SOFT_SERIAL_PIN); } inline static uint8_t serial_read_pin(void) ALWAYS_INLINE; -inline static -uint8_t serial_read_pin(void) { - return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK); -} +inline static uint8_t serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); } inline static void serial_low(void) ALWAYS_INLINE; -inline static -void serial_low(void) { - SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK; -} +inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); } inline static void serial_high(void) ALWAYS_INLINE; -inline static -void serial_high(void) { - SERIAL_PIN_PORT |= SERIAL_PIN_MASK; -} +inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } -void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) -{ - Transaction_table = sstd_table; +void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) { + Transaction_table = sstd_table; Transaction_table_size = (uint8_t)sstd_table_size; serial_output(); serial_high(); } -void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) -{ - Transaction_table = sstd_table; +void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) { + Transaction_table = sstd_table; Transaction_table_size = (uint8_t)sstd_table_size; serial_input_with_pullup(); // Enable INT0-INT3,INT6 EIMSK |= EIMSK_BIT; -#if SERIAL_PIN_MASK == _BV(PE6) +# if SOFT_SERIAL_PIN == E6 // Trigger on falling edge of INT6 EICRB &= EICRx_BIT; -#else +# else // Trigger on falling edge of INT0-INT3 EICRA &= EICRx_BIT; -#endif +# endif } // Used by the sender to synchronize timing with the reciver. static void sync_recv(void) NO_INLINE; -static -void sync_recv(void) { - for (uint8_t i = 0; i < SERIAL_DELAY*5 && serial_read_pin(); i++ ) { - } - // This shouldn't hang if the target disconnects because the - // serial line will float to high if the target does disconnect. - while (!serial_read_pin()); +static void sync_recv(void) { + for (uint8_t i = 0; i < SERIAL_DELAY * 5 && serial_read_pin(); i++) { + } + // This shouldn't hang if the target disconnects because the + // serial line will float to high if the target does disconnect. + while (!serial_read_pin()) + ; } // Used by the reciver to send a synchronization signal to the sender. static void sync_send(void) NO_INLINE; -static -void sync_send(void) { - serial_low(); - serial_delay(); - serial_high(); +static void sync_send(void) { + serial_low(); + serial_delay(); + serial_high(); } // Reads a byte from the serial line @@ -279,92 +245,94 @@ static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE; static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) { uint8_t byte, i, p, pb; - _delay_sub_us(READ_WRITE_START_ADJUST); - for( i = 0, byte = 0, p = PARITY; i < bit; i++ ) { - serial_delay_half1(); // read the middle of pulses - if( serial_read_pin() ) { - byte = (byte << 1) | 1; p ^= 1; - } else { - byte = (byte << 1) | 0; p ^= 0; - } - _delay_sub_us(READ_WRITE_WIDTH_ADJUST); - serial_delay_half2(); - } - /* recive parity bit */ - serial_delay_half1(); // read the middle of pulses - pb = serial_read_pin(); - _delay_sub_us(READ_WRITE_WIDTH_ADJUST); - serial_delay_half2(); - - *pterrcount += (p != pb)? 1 : 0; - - return byte; + _delay_sub_us(READ_WRITE_START_ADJUST); + for (i = 0, byte = 0, p = PARITY; i < bit; i++) { + serial_delay_half1(); // read the middle of pulses + if (serial_read_pin()) { + byte = (byte << 1) | 1; + p ^= 1; + } else { + byte = (byte << 1) | 0; + p ^= 0; + } + _delay_sub_us(READ_WRITE_WIDTH_ADJUST); + serial_delay_half2(); + } + /* recive parity bit */ + serial_delay_half1(); // read the middle of pulses + pb = serial_read_pin(); + _delay_sub_us(READ_WRITE_WIDTH_ADJUST); + serial_delay_half2(); + + *pterrcount += (p != pb) ? 1 : 0; + + return byte; } // Sends a byte with MSB ordering void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE; void serial_write_chunk(uint8_t data, uint8_t bit) { uint8_t b, p; - for( p = PARITY, b = 1<<(bit-1); b ; b >>= 1) { - if(data & b) { - serial_high(); p ^= 1; + for (p = PARITY, b = 1 << (bit - 1); b; b >>= 1) { + if (data & b) { + serial_high(); + p ^= 1; } else { - serial_low(); p ^= 0; + serial_low(); + p ^= 0; } serial_delay(); } /* send parity bit */ - if(p & 1) { serial_high(); } - else { serial_low(); } + if (p & 1) { + serial_high(); + } else { + serial_low(); + } serial_delay(); - serial_low(); // sync_send() / senc_recv() need raise edge + serial_low(); // sync_send() / senc_recv() need raise edge } static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE; -static -void serial_send_packet(uint8_t *buffer, uint8_t size) { - for (uint8_t i = 0; i < size; ++i) { - uint8_t data; - data = buffer[i]; - sync_send(); - serial_write_chunk(data,8); - } +static void serial_send_packet(uint8_t *buffer, uint8_t size) { + for (uint8_t i = 0; i < size; ++i) { + uint8_t data; + data = buffer[i]; + sync_send(); + serial_write_chunk(data, 8); + } } static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE; -static -uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) { - uint8_t pecount = 0; - for (uint8_t i = 0; i < size; ++i) { - uint8_t data; - sync_recv(); - data = serial_read_chunk(&pecount, 8); - buffer[i] = data; - } - return pecount == 0; +static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) { + uint8_t pecount = 0; + for (uint8_t i = 0; i < size; ++i) { + uint8_t data; + sync_recv(); + data = serial_read_chunk(&pecount, 8); + buffer[i] = data; + } + return pecount == 0; } -inline static -void change_sender2reciver(void) { - sync_send(); //0 - serial_delay_half1(); //1 - serial_low(); //2 - serial_input_with_pullup(); //2 - serial_delay_half1(); //3 +inline static void change_sender2reciver(void) { + sync_send(); // 0 + serial_delay_half1(); // 1 + serial_low(); // 2 + serial_input_with_pullup(); // 2 + serial_delay_half1(); // 3 } -inline static -void change_reciver2sender(void) { - sync_recv(); //0 - serial_delay(); //1 - serial_low(); //3 - serial_output(); //3 - serial_delay_half1(); //4 +inline static void change_reciver2sender(void) { + sync_recv(); // 0 + serial_delay(); // 1 + serial_low(); // 3 + serial_output(); // 3 + serial_delay_half1(); // 4 } -static inline uint8_t nibble_bits_count(uint8_t bits) -{ +static inline uint8_t nibble_bits_count(uint8_t bits) { bits = (bits & 0x5) + (bits >> 1 & 0x5); bits = (bits & 0x3) + (bits >> 2 & 0x3); return bits; @@ -372,51 +340,47 @@ static inline uint8_t nibble_bits_count(uint8_t bits) // interrupt handle to be used by the target device ISR(SERIAL_PIN_INTERRUPT) { +# ifndef SERIAL_USE_MULTI_TRANSACTION + serial_low(); + serial_output(); + SSTD_t *trans = Transaction_table; +# else + // recive transaction table index + uint8_t tid, bits; + uint8_t pecount = 0; + sync_recv(); + bits = serial_read_chunk(&pecount, 7); + tid = bits >> 3; + bits = (bits & 7) != nibble_bits_count(tid); + if (bits || pecount > 0 || tid > Transaction_table_size) { + return; + } + serial_delay_half1(); -#ifndef SERIAL_USE_MULTI_TRANSACTION - serial_low(); - serial_output(); - SSTD_t *trans = Transaction_table; -#else - // recive transaction table index - uint8_t tid, bits; - uint8_t pecount = 0; - sync_recv(); - bits = serial_read_chunk(&pecount,7); - tid = bits>>3; - bits = (bits&7) != nibble_bits_count(tid); - if( bits || pecount> 0 || tid > Transaction_table_size ) { - return; - } - serial_delay_half1(); - - serial_high(); // response step1 low->high - serial_output(); - _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT*SLAVE_INT_ACK_WIDTH); - SSTD_t *trans = &Transaction_table[tid]; - serial_low(); // response step2 ack high->low -#endif + serial_high(); // response step1 low->high + serial_output(); + _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH); + SSTD_t *trans = &Transaction_table[tid]; + serial_low(); // response step2 ack high->low +# endif + + // target send phase + if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size); + // target switch to input + change_sender2reciver(); + + // target recive phase + if (trans->initiator2target_buffer_size > 0) { + if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size)) { + *trans->status = TRANSACTION_ACCEPTED; + } else { + *trans->status = TRANSACTION_DATA_ERROR; + } + } else { + *trans->status = TRANSACTION_ACCEPTED; + } - // target send phase - if( trans->target2initiator_buffer_size > 0 ) - serial_send_packet((uint8_t *)trans->target2initiator_buffer, - trans->target2initiator_buffer_size); - // target switch to input - change_sender2reciver(); - - // target recive phase - if( trans->initiator2target_buffer_size > 0 ) { - if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, - trans->initiator2target_buffer_size) ) { - *trans->status = TRANSACTION_ACCEPTED; - } else { - *trans->status = TRANSACTION_DATA_ERROR; - } - } else { - *trans->status = TRANSACTION_ACCEPTED; - } - - sync_recv(); //weit initiator output to high + sync_recv(); // weit initiator output to high } ///////// @@ -429,105 +393,103 @@ ISR(SERIAL_PIN_INTERRUPT) { // TRANSACTION_NO_RESPONSE // TRANSACTION_DATA_ERROR // this code is very time dependent, so we need to disable interrupts -#ifndef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_transaction(void) { - SSTD_t *trans = Transaction_table; -#else -int soft_serial_transaction(int sstd_index) { - if( sstd_index > Transaction_table_size ) - return TRANSACTION_TYPE_ERROR; - SSTD_t *trans = &Transaction_table[sstd_index]; -#endif - cli(); +# ifndef SERIAL_USE_MULTI_TRANSACTION +int soft_serial_transaction(void) { + SSTD_t *trans = Transaction_table; +# else +int soft_serial_transaction(int sstd_index) { + if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR; + SSTD_t *trans = &Transaction_table[sstd_index]; +# endif + cli(); - // signal to the target that we want to start a transaction - serial_output(); - serial_low(); - _delay_us(SLAVE_INT_WIDTH_US); + // signal to the target that we want to start a transaction + serial_output(); + serial_low(); + _delay_us(SLAVE_INT_WIDTH_US); -#ifndef SERIAL_USE_MULTI_TRANSACTION - // wait for the target response - serial_input_with_pullup(); - _delay_us(SLAVE_INT_RESPONSE_TIME); +# ifndef SERIAL_USE_MULTI_TRANSACTION + // wait for the target response + serial_input_with_pullup(); + _delay_us(SLAVE_INT_RESPONSE_TIME); + + // check if the target is present + if (serial_read_pin()) { + // target failed to pull the line low, assume not present + serial_output(); + serial_high(); + *trans->status = TRANSACTION_NO_RESPONSE; + sei(); + return TRANSACTION_NO_RESPONSE; + } - // check if the target is present - if (serial_read_pin()) { - // target failed to pull the line low, assume not present - serial_output(); - serial_high(); - *trans->status = TRANSACTION_NO_RESPONSE; - sei(); - return TRANSACTION_NO_RESPONSE; - } - -#else - // send transaction table index - int tid = (sstd_index<<3) | (7 & nibble_bits_count(sstd_index)); - sync_send(); - _delay_sub_us(TID_SEND_ADJUST); - serial_write_chunk(tid, 7); - serial_delay_half1(); - - // wait for the target response (step1 low->high) - serial_input_with_pullup(); - while( !serial_read_pin() ) { - _delay_sub_us(2); - } - - // check if the target is present (step2 high->low) - for( int i = 0; serial_read_pin(); i++ ) { - if (i > SLAVE_INT_ACK_WIDTH + 1) { - // slave failed to pull the line low, assume not present - serial_output(); - serial_high(); - *trans->status = TRANSACTION_NO_RESPONSE; - sei(); - return TRANSACTION_NO_RESPONSE; - } - _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); - } -#endif +# else + // send transaction table index + int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index)); + sync_send(); + _delay_sub_us(TID_SEND_ADJUST); + serial_write_chunk(tid, 7); + serial_delay_half1(); + + // wait for the target response (step1 low->high) + serial_input_with_pullup(); + while (!serial_read_pin()) { + _delay_sub_us(2); + } + + // check if the target is present (step2 high->low) + for (int i = 0; serial_read_pin(); i++) { + if (i > SLAVE_INT_ACK_WIDTH + 1) { + // slave failed to pull the line low, assume not present + serial_output(); + serial_high(); + *trans->status = TRANSACTION_NO_RESPONSE; + sei(); + return TRANSACTION_NO_RESPONSE; + } + _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); + } +# endif + + // initiator recive phase + // if the target is present syncronize with it + if (trans->target2initiator_buffer_size > 0) { + if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size)) { + serial_output(); + serial_high(); + *trans->status = TRANSACTION_DATA_ERROR; + sei(); + return TRANSACTION_DATA_ERROR; + } + } + + // initiator switch to output + change_reciver2sender(); + + // initiator send phase + if (trans->initiator2target_buffer_size > 0) { + serial_send_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size); + } - // initiator recive phase - // if the target is present syncronize with it - if( trans->target2initiator_buffer_size > 0 ) { - if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, - trans->target2initiator_buffer_size) ) { - serial_output(); - serial_high(); - *trans->status = TRANSACTION_DATA_ERROR; - sei(); - return TRANSACTION_DATA_ERROR; - } - } - - // initiator switch to output - change_reciver2sender(); - - // initiator send phase - if( trans->initiator2target_buffer_size > 0 ) { - serial_send_packet((uint8_t *)trans->initiator2target_buffer, - trans->initiator2target_buffer_size); - } - - // always, release the line when not in use - sync_send(); - - *trans->status = TRANSACTION_END; - sei(); - return TRANSACTION_END; + // always, release the line when not in use + sync_send(); + + *trans->status = TRANSACTION_END; + sei(); + return TRANSACTION_END; } -#ifdef SERIAL_USE_MULTI_TRANSACTION +# ifdef SERIAL_USE_MULTI_TRANSACTION int soft_serial_get_and_clean_status(int sstd_index) { SSTD_t *trans = &Transaction_table[sstd_index]; cli(); - int retval = *trans->status; - *trans->status = 0;; + int retval = *trans->status; + *trans->status = 0; + ; sei(); return retval; } -#endif +# endif #endif diff --git a/quantum/split_common/serial.h b/quantum/split_common/serial.h index 1c1e640069..53e66cf905 100644 --- a/quantum/split_common/serial.h +++ b/quantum/split_common/serial.h @@ -22,14 +22,14 @@ // ///////////////////////////////////////////////////////////////// // Soft Serial Transaction Descriptor -typedef struct _SSTD_t { +typedef struct _SSTD_t { uint8_t *status; - uint8_t initiator2target_buffer_size; + uint8_t initiator2target_buffer_size; uint8_t *initiator2target_buffer; - uint8_t target2initiator_buffer_size; + uint8_t target2initiator_buffer_size; uint8_t *target2initiator_buffer; } SSTD_t; -#define TID_LIMIT( table ) (sizeof(table) / sizeof(SSTD_t)) +#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t)) // initiator is transaction start side void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size); @@ -39,12 +39,12 @@ void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size); // initiator resullt #define TRANSACTION_END 0 #define TRANSACTION_NO_RESPONSE 0x1 -#define TRANSACTION_DATA_ERROR 0x2 -#define TRANSACTION_TYPE_ERROR 0x4 +#define TRANSACTION_DATA_ERROR 0x2 +#define TRANSACTION_TYPE_ERROR 0x4 #ifndef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_transaction(void); +int soft_serial_transaction(void); #else -int soft_serial_transaction(int sstd_index); +int soft_serial_transaction(int sstd_index); #endif // target status @@ -58,5 +58,5 @@ int soft_serial_transaction(int sstd_index); // or TRANSACTION_ACCEPTED #define TRANSACTION_ACCEPTED 0x8 #ifdef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_get_and_clean_status(int sstd_index); +int soft_serial_get_and_clean_status(int sstd_index); #endif diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 09a307b8ed..5c548de059 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -7,86 +7,101 @@ #include "quantum.h" #ifdef EE_HANDS -# include "tmk_core/common/eeprom.h" -# include "eeconfig.h" +# include "eeconfig.h" #endif #if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) -#include "rgblight.h" +# include "rgblight.h" +#endif + +#ifndef SPLIT_USB_TIMEOUT +# define SPLIT_USB_TIMEOUT 2500 #endif volatile bool isLeftHand = true; -__attribute__((weak)) -bool is_keyboard_left(void) { - #if defined(SPLIT_HAND_PIN) +bool waitForUsb(void) { + for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / 100); i++) { + // This will return true of a USB connection has been established +#if defined(__AVR__) + if (UDADDR & _BV(ADDEN)) { +#else + if (usbGetDriverStateI(&USBD1) == USB_ACTIVE) { +#endif + return true; + } + wait_ms(100); + } + +#if defined(__AVR__) + // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow + (USBCON &= ~(_BV(USBE) | _BV(OTGPADE))); +#endif + + return false; +} + +__attribute__((weak)) bool is_keyboard_left(void) { +#if defined(SPLIT_HAND_PIN) // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand setPinInput(SPLIT_HAND_PIN); return readPin(SPLIT_HAND_PIN); - #elif defined(EE_HANDS) - return eeprom_read_byte(EECONFIG_HANDEDNESS); - #elif defined(MASTER_RIGHT) +#elif defined(EE_HANDS) + return eeconfig_read_handedness(); +#elif defined(MASTER_RIGHT) return !is_keyboard_master(); - #endif +#endif - return is_keyboard_master(); + return is_keyboard_master(); } -bool is_keyboard_master(void) -{ -#ifdef __AVR__ - static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN; +__attribute__((weak)) bool is_keyboard_master(void) { + static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN; - // only check once, as this is called often - if (usbstate == UNKNOWN) - { - USBCON |= (1 << OTGPADE); // enables VBUS pad - wait_us(5); + // only check once, as this is called often + if (usbstate == UNKNOWN) { +#if defined(SPLIT_USB_DETECT) || defined(PROTOCOL_CHIBIOS) + usbstate = waitForUsb() ? MASTER : SLAVE; +#elif defined(__AVR__) + USBCON |= (1 << OTGPADE); // enables VBUS pad + wait_us(5); - usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE; // checks state of VBUS - } - - return (usbstate == MASTER); + usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE; // checks state of VBUS #else - return true; + usbstate = MASTER; #endif + } + + return (usbstate == MASTER); } static void keyboard_master_setup(void) { #if defined(USE_I2C) || defined(EH) - #ifdef SSD1306OLED - matrix_master_OLED_init (); - #endif +# ifdef SSD1306OLED + matrix_master_OLED_init(); +# endif #endif - transport_master_init(); + transport_master_init(); } -static void keyboard_slave_setup(void) -{ - transport_slave_init(); -} +static void keyboard_slave_setup(void) { transport_slave_init(); } -// this code runs before the usb and keyboard is initialized -void matrix_setup(void) -{ - isLeftHand = is_keyboard_left(); +// this code runs before the keyboard is fully initialized +void keyboard_split_setup(void) { + isLeftHand = is_keyboard_left(); #if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) - uint8_t num_rgb_leds_split[2] = RGBLED_SPLIT; - if (isLeftHand) { - rgblight_set_clipping_range(0, num_rgb_leds_split[0]); - } - else { - rgblight_set_clipping_range(num_rgb_leds_split[0], num_rgb_leds_split[1]); - } + uint8_t num_rgb_leds_split[2] = RGBLED_SPLIT; + if (isLeftHand) { + rgblight_set_clipping_range(0, num_rgb_leds_split[0]); + } else { + rgblight_set_clipping_range(num_rgb_leds_split[0], num_rgb_leds_split[1]); + } #endif - if (is_keyboard_master()) - { - keyboard_master_setup(); - } - else - { - keyboard_slave_setup(); - } + if (is_keyboard_master()) { + keyboard_master_setup(); + } else { + keyboard_slave_setup(); + } } diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index 20f7535bf4..5d9c523400 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -7,4 +7,5 @@ extern volatile bool isLeftHand; -void matrix_master_OLED_init (void); +void matrix_master_OLED_init(void); +void keyboard_split_setup(void); diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index b32d48eb88..3c783dc568 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -8,99 +8,100 @@ #define ROWS_PER_HAND (MATRIX_ROWS / 2) #ifdef RGBLIGHT_ENABLE -# include "rgblight.h" +# include "rgblight.h" #endif #ifdef BACKLIGHT_ENABLE -# include "backlight.h" +# include "backlight.h" #endif #ifdef ENCODER_ENABLE -# include "encoder.h" +# include "encoder.h" +static pin_t encoders_pad[] = ENCODERS_PAD_A; +# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) #endif #if defined(USE_I2C) || defined(EH) -# include "i2c_master.h" -# include "i2c_slave.h" +# include "i2c_master.h" +# include "i2c_slave.h" typedef struct _I2C_slave_buffer_t { matrix_row_t smatrix[ROWS_PER_HAND]; uint8_t backlight_level; -#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) rgblight_syncinfo_t rgblight_sync; -#endif -#ifdef ENCODER_ENABLE +# endif +# ifdef ENCODER_ENABLE uint8_t encoder_state[NUMBER_OF_ENCODERS]; -#endif +# endif } I2C_slave_buffer_t; -static I2C_slave_buffer_t * const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; +static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; -# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) -# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) -# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix) -# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) +# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) +# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) +# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix) +# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) -# define TIMEOUT 100 +# define TIMEOUT 100 -# ifndef SLAVE_I2C_ADDRESS -# define SLAVE_I2C_ADDRESS 0x32 -# endif +# ifndef SLAVE_I2C_ADDRESS +# define SLAVE_I2C_ADDRESS 0x32 +# endif // Get rows from other half over i2c bool transport_master(matrix_row_t matrix[]) { - i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); - - // write backlight info -# ifdef BACKLIGHT_ENABLE - uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; - if (level != i2c_buffer->backlight_level) { - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { - i2c_buffer->backlight_level = level; + i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); + + // write backlight info +# ifdef BACKLIGHT_ENABLE + uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; + if (level != i2c_buffer->backlight_level) { + if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { + i2c_buffer->backlight_level = level; + } } - } -# endif - -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - if (rgblight_get_change_flags()) { - rgblight_syncinfo_t rgblight_sync; - rgblight_get_syncinfo(&rgblight_sync); - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, - (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) { - rgblight_clear_change_flags(); +# endif + +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + if (rgblight_get_change_flags()) { + rgblight_syncinfo_t rgblight_sync; + rgblight_get_syncinfo(&rgblight_sync); + if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) { + rgblight_clear_change_flags(); + } } - } -# endif +# endif -# ifdef ENCODER_ENABLE - i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT); - encoder_update_raw(i2c_buffer->encoder_state); -# endif +# ifdef ENCODER_ENABLE + i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT); + encoder_update_raw(i2c_buffer->encoder_state); +# endif - return true; + return true; } void transport_slave(matrix_row_t matrix[]) { - // Copy matrix to I2C buffer - memcpy((void*)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix)); + // Copy matrix to I2C buffer + memcpy((void *)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix)); // Read Backlight Info -# ifdef BACKLIGHT_ENABLE - backlight_set(i2c_buffer->backlight_level); -# endif - -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - // Update the RGB with the new data - if (i2c_buffer->rgblight_sync.status.change_flags != 0) { - rgblight_update_sync(&i2c_buffer->rgblight_sync, false); - i2c_buffer->rgblight_sync.status.change_flags = 0; - } -# endif - -# ifdef ENCODER_ENABLE - encoder_state_raw(i2c_buffer->encoder_state); -# endif +# ifdef BACKLIGHT_ENABLE + backlight_set(i2c_buffer->backlight_level); +# endif + +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + // Update the RGB with the new data + if (i2c_buffer->rgblight_sync.status.change_flags != 0) { + rgblight_update_sync(&i2c_buffer->rgblight_sync, false); + i2c_buffer->rgblight_sync.status.change_flags = 0; + } +# endif + +# ifdef ENCODER_ENABLE + encoder_state_raw(i2c_buffer->encoder_state); +# endif } void transport_master_init(void) { i2c_init(); } @@ -109,25 +110,25 @@ void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } #else // USE_SERIAL -# include "serial.h" +# include "serial.h" typedef struct _Serial_s2m_buffer_t { - // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack - matrix_row_t smatrix[ROWS_PER_HAND]; + // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack + matrix_row_t smatrix[ROWS_PER_HAND]; -# ifdef ENCODER_ENABLE - uint8_t encoder_state[NUMBER_OF_ENCODERS]; -# endif +# ifdef ENCODER_ENABLE + uint8_t encoder_state[NUMBER_OF_ENCODERS]; +# endif } Serial_s2m_buffer_t; typedef struct _Serial_m2s_buffer_t { -# ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; -# endif +# ifdef BACKLIGHT_ENABLE + uint8_t backlight_level; +# endif } Serial_m2s_buffer_t; -#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) // When MCUs on both sides drive their respective RGB LED chains, // it is necessary to synchronize, so it is necessary to communicate RGB // information. In that case, define RGBLIGHT_SPLIT with info on the number @@ -142,7 +143,7 @@ typedef struct _Serial_rgblight_t { volatile Serial_rgblight_t serial_rgblight = {}; uint8_t volatile status_rgblight = 0; -#endif +# endif volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; @@ -150,102 +151,99 @@ uint8_t volatile status0 = 0; enum serial_transaction_id { GET_SLAVE_MATRIX = 0, -#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) PUT_RGBLIGHT, -#endif +# endif }; SSTD_t transactions[] = { - [GET_SLAVE_MATRIX] = { - (uint8_t *)&status0, - sizeof(serial_m2s_buffer), - (uint8_t *)&serial_m2s_buffer, - sizeof(serial_s2m_buffer), - (uint8_t *)&serial_s2m_buffer, - }, -#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - [PUT_RGBLIGHT] = { - (uint8_t *)&status_rgblight, - sizeof(serial_rgblight), - (uint8_t *)&serial_rgblight, - 0, NULL // no slave to master transfer - }, -#endif + [GET_SLAVE_MATRIX] = + { + (uint8_t *)&status0, + sizeof(serial_m2s_buffer), + (uint8_t *)&serial_m2s_buffer, + sizeof(serial_s2m_buffer), + (uint8_t *)&serial_s2m_buffer, + }, +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + [PUT_RGBLIGHT] = + { + (uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer + }, +# endif }; void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } -#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) // rgblight synchronization information communication. void transport_rgblight_master(void) { - if (rgblight_get_change_flags()) { - rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync); - if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) { - rgblight_clear_change_flags(); + if (rgblight_get_change_flags()) { + rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync); + if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) { + rgblight_clear_change_flags(); + } } - } } void transport_rgblight_slave(void) { - if (status_rgblight == TRANSACTION_ACCEPTED) { - rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, - false); - status_rgblight = TRANSACTION_END; - } + if (status_rgblight == TRANSACTION_ACCEPTED) { + rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false); + status_rgblight = TRANSACTION_END; + } } -#else -#define transport_rgblight_master() -#define transport_rgblight_slave() -#endif +# else +# define transport_rgblight_master() +# define transport_rgblight_slave() +# endif bool transport_master(matrix_row_t matrix[]) { -#ifndef SERIAL_USE_MULTI_TRANSACTION - if (soft_serial_transaction() != TRANSACTION_END) { - return false; - } -#else - transport_rgblight_master(); - if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) { - return false; - } -#endif +# ifndef SERIAL_USE_MULTI_TRANSACTION + if (soft_serial_transaction() != TRANSACTION_END) { + return false; + } +# else + transport_rgblight_master(); + if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) { + return false; + } +# endif - // TODO: if MATRIX_COLS > 8 change to unpack() - for (int i = 0; i < ROWS_PER_HAND; ++i) { - matrix[i] = serial_s2m_buffer.smatrix[i]; - } + // TODO: if MATRIX_COLS > 8 change to unpack() + for (int i = 0; i < ROWS_PER_HAND; ++i) { + matrix[i] = serial_s2m_buffer.smatrix[i]; + } -# ifdef BACKLIGHT_ENABLE - // Write backlight level for slave to read - serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0; -# endif +# ifdef BACKLIGHT_ENABLE + // Write backlight level for slave to read + serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0; +# endif -# ifdef ENCODER_ENABLE - encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state); -# endif +# ifdef ENCODER_ENABLE + encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state); +# endif - return true; + return true; } void transport_slave(matrix_row_t matrix[]) { - transport_rgblight_slave(); - // TODO: if MATRIX_COLS > 8 change to pack() - for (int i = 0; i < ROWS_PER_HAND; ++i) { - serial_s2m_buffer.smatrix[i] = matrix[i]; - } -# ifdef BACKLIGHT_ENABLE - backlight_set(serial_m2s_buffer.backlight_level); -# endif - -# ifdef ENCODER_ENABLE - encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state); -# endif + transport_rgblight_slave(); + // TODO: if MATRIX_COLS > 8 change to pack() + for (int i = 0; i < ROWS_PER_HAND; ++i) { + serial_s2m_buffer.smatrix[i] = matrix[i]; + } +# ifdef BACKLIGHT_ENABLE + backlight_set(serial_m2s_buffer.backlight_level); +# endif +# ifdef ENCODER_ENABLE + encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state); +# endif } #endif |