From 155e9310ff685f557287749bef2e02510538a6d9 Mon Sep 17 00:00:00 2001
From: Takeshi ISHII <2170248+mtei@users.noreply.github.com>
Date: Sat, 15 Dec 2018 04:00:10 +0900
Subject: Make quantum/split_common/serial.[ch] configurable (#4419)
* add temporary compile test shell script
* add 'CONFIG_H += serial_backward_compatibility.h' into common_features.mk:SPLIT_KEYBOARD block
* add quantum/split_common/serial_backward_compatibility.h
SERIAL_PIN_PORT and other PIN define move to serial_backward_compatibility.h
SERIAL_BACKLIT_START move to split_util.h
* quantum/split_common/serial.c change to helix-serial.c style serial configuration
* add temporary file quantum/split_common/split-keyboards-list.txt
* add '#define SOFT_SERIAL_PIN D0' to keyboards/6lit/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/divergetm2/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/ergotravel/rev1/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/foobar/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/handwired/dactyl_manuform/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/handwired/qc60/config.h
* add '//#define SOFT_SERIAL_PIN D0' to keyboards/handwired/xealous/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/iris/rev*/config.h
* add '//#define SOFT_SERIAL_PIN D0' to keyboards/lets_split_eh/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/levinson/rev*/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/miniaxe/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/nyquist/rev?/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/quefrency/rev1/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/qwertyydox/config.h,keyboards/qwertyydox/rev1/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/redox/rev1/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/rorschach/rev1/config.h
* remove '#define SOFT_SERIAL_PIN D0' from quantum/split_common/serial_backward_compatibility.h
* remove temporary file quantum/split_common/split-keyboards-list.txt
* remove temporary compile test shell script
* Revert "remove temporary compile test shell script"
This reverts commit 15b0021b4092127b8d8a21f572642ad3702b46d4.
* update quantum/split_common/compile_split_test.sh for new keyboard test
* add '#define SOFT_SERIAL_PIN D0' to keyboards/diverge3/config.h
* add '#define SOFT_SERIAL_PIN D0' to keyboards/40percentclub/25/config.h
* remove temporary compile test shell script
* update docs/config_options.md, quantum/template/avr/config.h
* fix quantum/template/avr/config.h
* fix typo docs/config_options.md
---
quantum/split_common/serial.c | 53 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
(limited to 'quantum/split_common/serial.c')
diff --git a/quantum/split_common/serial.c b/quantum/split_common/serial.c
index 74bcbb6bf..f34f824d7 100644
--- a/quantum/split_common/serial.c
+++ b/quantum/split_common/serial.c
@@ -14,6 +14,59 @@
#ifndef USE_I2C
+#ifndef SOFT_SERIAL_PIN
+ #error quantum/split_common/serial.c need SOFT_SERIAL_PIN define
+#endif
+
+#ifdef __AVR_ATmega32U4__
+ // if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial.
+ #ifdef USE_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
+
// Serial pulse period in microseconds. Its probably a bad idea to lower this
// value.
#define SERIAL_DELAY 24
--
cgit v1.2.3-70-g09d2
From 8f790948e5f7ed62b2c56e1a6aa63dae89d5c860 Mon Sep 17 00:00:00 2001
From: Takeshi ISHII <2170248+mtei@users.noreply.github.com>
Date: Sat, 15 Dec 2018 14:31:56 +0900
Subject: Refactor quantum/split_common/i2c.c, quantum/split_common/serial.c
(#4522)
* add temporary compile test shell script
* Extended support of SKIP_VERSION to make invariant compile results during testing.
* build_keyboard.mk, tmk_core/rules.mk: add LIB_SRC, QUANTUM_LIB_SRC support
Support compiled object enclosed in library.
e.g.
```
LIB_SRC += xxxx.c
xxxx.c --> xxxx.o ---> xxxx.a
```
* remove 'ifdef/ifndef USE_I2C' from quantum/split_common/{i2c|serial}.c
* add SKIP_DEBUG_INFO into tmk_core/rules.mk
When SKIP_DEBUG_INFO=yes is specified, do not use the -g option at compile time.
* tmk_core/rules.mk: Library object need -fno-lto
* add SKIP_DEBUG_INFO=yes
* remove temporary compile test shell script
* add '#define SOFT_SERIAL_PIN D0' to keyboards/lets_split/rev?/config.h
* quantum/split_common/serial.c: Changed not to use USE_I2C.
---
build_keyboard.mk | 6 ++++++
common_features.mk | 6 +++---
keyboards/lets_split/rev1/config.h | 3 +++
keyboards/lets_split/rev2/config.h | 3 +++
keyboards/lets_split/sockets/config.h | 3 +++
quantum/split_common/i2c.c | 3 ---
quantum/split_common/serial.c | 16 ++++++----------
tmk_core/common/command.c | 4 ++++
tmk_core/rules.mk | 36 +++++++++++++++++++++++++++--------
9 files changed, 56 insertions(+), 24 deletions(-)
(limited to 'quantum/split_common/serial.c')
diff --git a/build_keyboard.mk b/build_keyboard.mk
index d225fe821..b639b92d3 100644
--- a/build_keyboard.mk
+++ b/build_keyboard.mk
@@ -34,6 +34,10 @@ $(error MASTER does not have a valid value(left/right))
endif
endif
+ifdef SKIP_VERSION
+ OPT_DEFS += -DSKIP_VERSION
+endif
+
# Determine which subfolders exist.
KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD)
KEYBOARD_FOLDER_PATH_2 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_1)))
@@ -278,6 +282,7 @@ ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
endif
# # project specific files
+SRC += $(patsubst %.c,%.clib,$(LIB_SRC))
SRC += $(KEYBOARD_SRC) \
$(KEYMAP_C) \
$(QUANTUM_SRC)
@@ -296,6 +301,7 @@ include $(TMK_PATH)/protocol.mk
include $(TMK_PATH)/common.mk
include bootloader.mk
+SRC += $(patsubst %.c,%.clib,$(QUANTUM_LIB_SRC))
SRC += $(TMK_COMMON_SRC)
OPT_DEFS += $(TMK_COMMON_DEFS)
EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS)
diff --git a/common_features.mk b/common_features.mk
index 97febe2e7..73aab5d84 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -270,7 +270,7 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
endif
OPT_DEFS += -DSPLIT_KEYBOARD
QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_flags.c \
- $(QUANTUM_DIR)/split_common/split_util.c \
- $(QUANTUM_DIR)/split_common/i2c.c \
- $(QUANTUM_DIR)/split_common/serial.c
+ $(QUANTUM_DIR)/split_common/split_util.c
+ QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/i2c.c
+ QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/serial.c
endif
diff --git a/keyboards/lets_split/rev1/config.h b/keyboards/lets_split/rev1/config.h
index a8d614915..18b7cce5a 100644
--- a/keyboards/lets_split/rev1/config.h
+++ b/keyboards/lets_split/rev1/config.h
@@ -45,6 +45,9 @@ along with this program. If not, see .
/* Set 0 if debouncing isn't needed */
#define DEBOUNCING_DELAY 5
+/* serial.c configuration for split keyboard */
+#define SOFT_SERIAL_PIN D0
+
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
diff --git a/keyboards/lets_split/rev2/config.h b/keyboards/lets_split/rev2/config.h
index 8844e5bb8..1c0871cd1 100644
--- a/keyboards/lets_split/rev2/config.h
+++ b/keyboards/lets_split/rev2/config.h
@@ -45,6 +45,9 @@ along with this program. If not, see .
/* Set 0 if debouncing isn't needed */
#define DEBOUNCING_DELAY 5
+/* serial.c configuration for split keyboard */
+#define SOFT_SERIAL_PIN D0
+
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
diff --git a/keyboards/lets_split/sockets/config.h b/keyboards/lets_split/sockets/config.h
index 10d0c997e..6939d37dc 100644
--- a/keyboards/lets_split/sockets/config.h
+++ b/keyboards/lets_split/sockets/config.h
@@ -45,6 +45,9 @@ along with this program. If not, see .
/* Set 0 if debouncing isn't needed */
#define DEBOUNCING_DELAY 5
+/* serial.c configuration for split keyboard */
+#define SOFT_SERIAL_PIN D0
+
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
diff --git a/quantum/split_common/i2c.c b/quantum/split_common/i2c.c
index b3d7fcc68..45e958b39 100644
--- a/quantum/split_common/i2c.c
+++ b/quantum/split_common/i2c.c
@@ -7,8 +7,6 @@
#include "i2c.h"
#include "split_flags.h"
-#if defined(USE_I2C) || defined(EH)
-
// Limits the amount of we wait for any one i2c transaction.
// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is
// 9 bits, a single transaction will take around 90μs to complete.
@@ -184,4 +182,3 @@ ISR(TWI_vect) {
// Reset everything, so we are ready for the next TWI interrupt
TWCR |= (1<
#include "serial.h"
-#ifndef USE_I2C
-
-#ifndef SOFT_SERIAL_PIN
- #error quantum/split_common/serial.c need SOFT_SERIAL_PIN define
-#endif
+#ifdef SOFT_SERIAL_PIN
#ifdef __AVR_ATmega32U4__
// if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial.
- #ifdef USE_I2C
- #if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1
- #error Using ATmega32U4 I2C, so can not use PD0, PD1
- #endif
+ #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
@@ -278,4 +274,4 @@ int serial_update_buffers(void) {
return 0;
}
-#endif
+#endif /* SOFT_SERIAL_PIN */
diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c
index f79d5a257..aab99290d 100644
--- a/tmk_core/common/command.c
+++ b/tmk_core/common/command.c
@@ -181,7 +181,11 @@ static void print_version(void)
print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
"PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
"VER: " STR(DEVICE_VER) "\n");
+#ifdef SKIP_VERSION
+ print("BUILD: (" __DATE__ ")\n");
+#else
print("BUILD: " STR(QMK_VERSION) " (" __TIME__ " " __DATE__ ")\n");
+#endif
/* build options */
print("OPTIONS:"
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
index ce3cd83b3..2e419dd66 100644
--- a/tmk_core/rules.mk
+++ b/tmk_core/rules.mk
@@ -28,12 +28,13 @@ VPATH :=
# Convert all SRC to OBJ
define OBJ_FROM_SRC
-$(patsubst %.c,$1/%.o,$(patsubst %.cpp,$1/%.o,$(patsubst %.cc,$1/%.o,$(patsubst %.S,$1/%.o,$($1_SRC)))))
+$(patsubst %.c,$1/%.o,$(patsubst %.cpp,$1/%.o,$(patsubst %.cc,$1/%.o,$(patsubst %.S,$1/%.o,$(patsubst %.clib,$1/%.a,$($1_SRC))))))
endef
$(foreach OUTPUT,$(OUTPUTS),$(eval $(OUTPUT)_OBJ +=$(call OBJ_FROM_SRC,$(OUTPUT))))
# Define a list of all objects
OBJ := $(foreach OUTPUT,$(OUTPUTS),$($(OUTPUT)_OBJ))
+NO_LTO_OBJ := $(filter %.a,$(OBJ))
MASTER_OUTPUT := $(firstword $(OUTPUTS))
@@ -81,7 +82,9 @@ CSTANDARD = -std=gnu99
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
-CFLAGS += -g$(DEBUG)
+ifndef SKIP_DEBUG_INFO
+ CFLAGS += -g$(DEBUG)
+endif
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
# add color
@@ -110,7 +113,9 @@ CFLAGS += $(CSTANDARD)
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
-CPPFLAGS += -g$(DEBUG)
+ifndef SKIP_DEBUG_INFO
+ CPPFLAGS += -g$(DEBUG)
+endif
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
# to supress "warning: only initialized variables can be placed into program memory area"
@@ -138,7 +143,11 @@ CPPFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
# dump that will be displayed for a given single line of source input.
ASFLAGS += $(ADEFS)
-ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
+ifndef SKIP_DEBUG_INFO
+ ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
+else
+ ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),--listing-cont-lines=100
+endif
#---------------- Library Options ----------------
# Minimalistic printf version
@@ -210,6 +219,11 @@ ALL_CFLAGS = $(MCUFLAGS) $(CFLAGS) $(EXTRAFLAGS)
ALL_CPPFLAGS = $(MCUFLAGS) -x c++ $(CPPFLAGS) $(EXTRAFLAGS)
ALL_ASFLAGS = $(MCUFLAGS) -x assembler-with-cpp $(ASFLAGS) $(EXTRAFLAGS)
+define NO_LTO
+$(patsubst %.a,%.o,$1): NOLTO_CFLAGS += -fno-lto
+endef
+$(foreach LOBJ, $(NO_LTO_OBJ), $(eval $(call NO_LTO,$(LOBJ))))
+
MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@)
@@ -290,8 +304,8 @@ $1_INCFLAGS := $$(patsubst %,-I%,$$($1_INC))
ifdef $1_CONFIG
$1_CONFIG_FLAGS += $$(patsubst %,-include %,$$($1_CONFIG))
endif
-$1_CFLAGS = $$(ALL_CFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS)
-$1_CPPFLAGS= $$(ALL_CPPFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS)
+$1_CFLAGS = $$(ALL_CFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS)
+$1_CPPFLAGS= $$(ALL_CPPFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS)
$1_ASFLAGS= $$(ALL_ASFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS)
# Compile: create object files from C source files.
@@ -321,6 +335,12 @@ $1/%.o : %.S $1/asflags.txt $1/compiler.txt | $(BEGIN)
$$(eval CMD=$$(CC) -c $$($1_ASFLAGS) $$< -o $$@)
@$$(BUILD_CMD)
+$1/%.a : $1/%.o
+ @mkdir -p $$(@D)
+ @$(SILENT) || printf "Archiving: $$<" | $$(AWK_CMD)
+ $$(eval CMD=$$(AR) $$@ $$<)
+ @$$(BUILD_CMD)
+
$1/force:
$1/cflags.txt: $1/force
@@ -346,7 +366,7 @@ $(MASTER_OUTPUT)/ldflags.txt: $(MASTER_OUTPUT)/force
# We have to use static rules for the .d files for some reason
-DEPS = $(patsubst %.o,%.d,$(OBJ))
+DEPS = $(patsubst %.o,%.d,$(patsubst %.a,%.o,$(OBJ)))
# Keep the .d files
.PRECIOUS: $(DEPS)
# Empty rule to force recompilation if the .d file is missing
@@ -391,7 +411,7 @@ $(shell mkdir -p $(BUILD_DIR) 2>/dev/null)
$(eval $(foreach OUTPUT,$(OUTPUTS),$(shell mkdir -p $(OUTPUT) 2>/dev/null)))
# Include the dependency files.
--include $(patsubst %.o,%.d,$(OBJ))
+-include $(patsubst %.o,%.d,$(patsubst %.a,%.o,$(OBJ)))
# Listing of phony targets.
--
cgit v1.2.3-70-g09d2
From 72d4e4bfd76b2c83b89787f8b3a8ba779a3e8d81 Mon Sep 17 00:00:00 2001
From: Takeshi ISHII <2170248+mtei@users.noreply.github.com>
Date: Tue, 25 Dec 2018 04:14:57 +0900
Subject: Replace serial.c of quantum/split_common/ (#4669)
* Add provisional Helix implementation to test the quantum/split_common.
* copy keyboards/helix/serial.[ch] to quantum/split_common/
* Make serial.c a pure driver.
Remove buffer name and buffer size from serial.c. They should be placed in the caller(matrix.c, split_utils.c).
* remove quantum/split_common/serial_backward_compatibility.h
* Changed array serial_master_buffer to structure serial_m2s_buffer.
* Changed array serial_slave_buffer to structure serial_s2m_buffer.
* Change keyboards/miniaxe/matrix.c
I also made changes to quantum/split_comon/matrix.c to keyboards/miniaxe/matrix.c.
Note: I contacted @ka2hiro, creator of miniaxe, and I got permission to change keyboards/miniaxe/matrix.c.
* update history comment in quantum/split_common/serial.c
* Revert "Add provisional Helix implementation to test the quantum/split_common."
This reverts commit 168c82ef82c88e79979d9796bab9cc819cc2f685.
* fix keyboards/miniaxe/matrix.c, quantum/split_common/matrix.c
avr-gcc 4.9.[23] report error.
avr-gcc 5.4.0, avr-gcc 7.3.0 pass.
It is funny.
* update comment quantum/split_common/serial.c
* Reserve RGBLIGHT_SPLIT macro in quantum/split_common
---
common_features.mk | 5 -
keyboards/miniaxe/matrix.c | 59 ++-
quantum/split_common/matrix.c | 61 ++-
quantum/split_common/matrix.h | 31 ++
quantum/split_common/serial.c | 505 ++++++++++++++++-----
quantum/split_common/serial.h | 65 ++-
.../split_common/serial_backward_compatibility.h | 11 -
quantum/split_common/split_util.c | 9 +-
quantum/split_common/split_util.h | 3 -
9 files changed, 578 insertions(+), 171 deletions(-)
create mode 100644 quantum/split_common/matrix.h
delete mode 100644 quantum/split_common/serial_backward_compatibility.h
(limited to 'quantum/split_common/serial.c')
diff --git a/common_features.mk b/common_features.mk
index 73aab5d84..883681324 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -263,11 +263,6 @@ ifneq ($(strip $(CUSTOM_MATRIX)), yes)
endif
ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
- SERIAL_BACKWARD_COMPAT := $(wildcard $(QUANTUM_DIR)/split_common/serial_backward_compatibility.h)
- ifneq ($(SERIAL_BACKWARD_COMPAT),)
- CONFIG_H += $(SERIAL_BACKWARD_COMPAT)
- # $(info CONFIG_H=$(CONFIG_H))
- endif
OPT_DEFS += -DSPLIT_KEYBOARD
QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_flags.c \
$(QUANTUM_DIR)/split_common/split_util.c
diff --git a/keyboards/miniaxe/matrix.c b/keyboards/miniaxe/matrix.c
index 55c458e1f..5fec1281d 100644
--- a/keyboards/miniaxe/matrix.c
+++ b/keyboards/miniaxe/matrix.c
@@ -32,9 +32,6 @@ along with this program. If not, see .
#include "timer.h"
#include "split_flags.h"
-#ifdef RGBLIGHT_ENABLE
-# include "rgblight.h"
-#endif
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
extern backlight_config_t backlight_config;
@@ -55,6 +52,8 @@ along with this program. If not, see .
static bool debouncing = false;
#endif
+#if defined(USE_I2C) || defined(EH)
+
#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))
@@ -62,6 +61,27 @@ along with this program. If not, see .
# define ROW_SHIFTER ((uint8_t)1)
#else
# error "Currently only supports 8 COLS"
+#endif
+
+#else // USE_SERIAL
+
+#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)
+#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)
+#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)
+#endif
+
#endif
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
@@ -315,15 +335,39 @@ i2c_error: // the cable is disconnceted, or something else went wrong
#else // USE_SERIAL
+
+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];
+} Serial_s2m_buffer_t;
+
+volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
+volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
+uint8_t volatile status0 = 0;
+
+SSTD_t transactions[] = {
+ { (uint8_t *)&status0,
+ sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer,
+ sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
+ }
+};
+
+void serial_master_init(void)
+{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
+
+void serial_slave_init(void)
+{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
+
int serial_transaction(void) {
int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
- if (serial_update_buffers()) {
+ if (soft_serial_transaction()) {
return 1;
}
+ // TODO: if MATRIX_COLS > 8 change to unpack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
- matrix[slaveOffset+i] = serial_slave_buffer[i];
+ matrix[slaveOffset+i] = serial_s2m_buffer.smatrix[i];
}
#ifdef RGBLIGHT_ENABLE
@@ -332,7 +376,7 @@ int serial_transaction(void) {
#ifdef BACKLIGHT_ENABLE
// Write backlight level for slave to read
- serial_master_buffer[SERIAL_BACKLIT_START] = backlight_config.enable ? backlight_config.level : 0;
+ serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
#endif
return 0;
@@ -375,8 +419,9 @@ void matrix_slave_scan(void) {
i2c_slave_buffer[I2C_KEYMAP_START+i] = matrix[offset+i];
}
#else // USE_SERIAL
+ // TODO: if MATRIX_COLS > 8 change to pack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
- serial_slave_buffer[i] = matrix[offset+i];
+ serial_s2m_buffer.smatrix[i] = matrix[offset+i];
}
#endif
matrix_slave_scan_user();
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index d6359b51f..261137638 100644
--- a/quantum/split_common/matrix.c
+++ b/quantum/split_common/matrix.c
@@ -32,9 +32,6 @@ along with this program. If not, see .
#include "timer.h"
#include "split_flags.h"
-#ifdef RGBLIGHT_ENABLE
-# include "rgblight.h"
-#endif
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
extern backlight_config_t backlight_config;
@@ -55,6 +52,8 @@ along with this program. If not, see .
static bool debouncing = false;
#endif
+#if defined(USE_I2C) || defined(EH)
+
#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))
@@ -62,6 +61,27 @@ along with this program. If not, see .
# define ROW_SHIFTER ((uint8_t)1)
#else
# error "Currently only supports 8 COLS"
+#endif
+
+#else // USE_SERIAL
+
+#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)
+#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)
+#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)
+#endif
+
#endif
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
@@ -286,24 +306,48 @@ i2c_error: // the cable is disconnceted, or something else went wrong
#else // USE_SERIAL
+
+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];
+} Serial_s2m_buffer_t;
+
+volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
+volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
+uint8_t volatile status0 = 0;
+
+SSTD_t transactions[] = {
+ { (uint8_t *)&status0,
+ sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer,
+ sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
+ }
+};
+
+void serial_master_init(void)
+{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
+
+void serial_slave_init(void)
+{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
+
int serial_transaction(void) {
int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
- if (serial_update_buffers()) {
+ if (soft_serial_transaction()) {
return 1;
}
+ // TODO: if MATRIX_COLS > 8 change to unpack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
- matrix[slaveOffset+i] = serial_slave_buffer[i];
+ matrix[slaveOffset+i] = serial_s2m_buffer.smatrix[i];
}
- #ifdef RGBLIGHT_ENABLE
+ #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
// Code to send RGB over serial goes here (not implemented yet)
#endif
#ifdef BACKLIGHT_ENABLE
// Write backlight level for slave to read
- serial_master_buffer[SERIAL_BACKLIT_START] = backlight_config.enable ? backlight_config.level : 0;
+ serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
#endif
return 0;
@@ -346,8 +390,9 @@ void matrix_slave_scan(void) {
i2c_slave_buffer[I2C_KEYMAP_START+i] = matrix[offset+i];
}
#else // USE_SERIAL
+ // TODO: if MATRIX_COLS > 8 change to pack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
- serial_slave_buffer[i] = matrix[offset+i];
+ serial_s2m_buffer.smatrix[i] = matrix[offset+i];
}
#endif
matrix_slave_scan_user();
diff --git a/quantum/split_common/matrix.h b/quantum/split_common/matrix.h
new file mode 100644
index 000000000..b5cb45bae
--- /dev/null
+++ b/quantum/split_common/matrix.h
@@ -0,0 +1,31 @@
+#ifndef SPLIT_COMMON_MATRIX_H
+#define SPLIT_COMMON_MATRIX_H
+
+#include
+
+#ifdef RGBLIGHT_ENABLE
+# include "rgblight.h"
+#endif
+
+typedef struct _Serial_m2s_buffer_t {
+#ifdef BACKLIGHT_ENABLE
+ uint8_t backlight_level;
+#endif
+#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
+ rgblight_config_t rgblight_config; //not yet use
+ //
+ // 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 the RGBLIGHT_SPLIT macro.
+ //
+ // Otherwise, if the master side MCU drives both sides RGB LED chains,
+ // there is no need to communicate.
+#endif
+} Serial_m2s_buffer_t;
+
+extern volatile Serial_m2s_buffer_t serial_m2s_buffer;
+
+void serial_master_init(void);
+void serial_slave_init(void);
+
+#endif
diff --git a/quantum/split_common/serial.c b/quantum/split_common/serial.c
index 13e58d825..4df8d103b 100644
--- a/quantum/split_common/serial.c
+++ b/quantum/split_common/serial.c
@@ -1,5 +1,10 @@
/*
* WARNING: be careful changing this code, it is very timing dependent
+ *
+ * 2018-10-28 checked
+ * avr-gcc 4.9.2
+ * avr-gcc 5.4.0
+ * avr-gcc 7.3.0
*/
#ifndef F_CPU
@@ -9,17 +14,19 @@
#include
#include
#include
+#include
#include
#include "serial.h"
+//#include
#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
+ #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
@@ -63,215 +70,477 @@
#error serial.c now support ATmega32U4 only
#endif
-// Serial pulse period in microseconds. Its probably a bad idea to lower this
-// value.
-#define SERIAL_DELAY 24
+#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
+// ============ Standard setups ============
+
+#ifndef SELECT_SOFT_SERIAL_SPEED
+#define SELECT_SOFT_SERIAL_SPEED 1
+// 0: about 189kbps (Experiment only)
+// 1: about 137kbps (default)
+// 2: about 75kbps
+// 3: about 39kbps
+// 4: about 26kbps
+// 5: about 20kbps
+#endif
-uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
-uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
+#if __GNUC__ < 6
+ #define TID_SEND_ADJUST 14
+#else
+ #define TID_SEND_ADJUST 2
+#endif
-#define SLAVE_DATA_CORRUPT (1<<0)
-volatile uint8_t status = 0;
+#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_half1(void) ALWAYS_INLINE;
+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_output(void) ALWAYS_INLINE;
inline static
void serial_output(void) {
SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
}
// 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(void) {
+void serial_input_with_pullup(void) {
SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK;
SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
}
+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 void serial_low(void) ALWAYS_INLINE;
inline static
void serial_low(void) {
SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
}
+inline static void serial_high(void) ALWAYS_INLINE;
inline static
void serial_high(void) {
SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
}
-void serial_master_init(void) {
- serial_output();
- serial_high();
+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 serial_slave_init(void) {
- serial_input();
-
- // Enable INT0
- EIMSK |= _BV(INT0);
- // Trigger on falling edge of INT0
- EICRA &= ~(_BV(ISC00) | _BV(ISC01));
+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)
+ // Trigger on falling edge of INT6
+ EICRB &= EICRx_BIT;
+#else
+ // Trigger on falling edge of INT0-INT3
+ EICRA &= EICRx_BIT;
+#endif
}
-// Used by the master to synchronize timing with the slave.
+// Used by the sender to synchronize timing with the reciver.
+static void sync_recv(void) NO_INLINE;
static
void sync_recv(void) {
- serial_input();
- // This shouldn't hang if the slave disconnects because the
- // serial line will float to high if the slave does disconnect.
+ 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());
- serial_delay();
}
-// Used by the slave to send a synchronization signal to the master.
+// 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_output();
-
serial_low();
serial_delay();
-
serial_high();
}
// Reads a byte from the serial line
-static
-uint8_t serial_read_byte(void) {
- uint8_t byte = 0;
- serial_input();
- for ( uint8_t i = 0; i < 8; ++i) {
- byte = (byte << 1) | serial_read_pin();
- serial_delay();
- _delay_us(1);
+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;
}
// Sends a byte with MSB ordering
-static
-void serial_write_byte(uint8_t data) {
- uint8_t b = 8;
- serial_output();
- while( b-- ) {
- if(data & (1 << b)) {
- serial_high();
- } else {
- serial_low();
+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;
+ } else {
+ serial_low(); p ^= 0;
+ }
+ serial_delay();
}
+ /* send parity bit */
+ if(p & 1) { serial_high(); }
+ else { serial_low(); }
serial_delay();
- }
-}
-// interrupt handle to be used by the slave device
-ISR(SERIAL_PIN_INTERRUPT) {
- sync_send();
+ serial_low(); // sync_send() / senc_recv() need raise edge
+}
- uint8_t checksum = 0;
- for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
- serial_write_byte(serial_slave_buffer[i]);
+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();
- checksum += serial_slave_buffer[i];
+ serial_write_chunk(data,8);
}
- serial_write_byte(checksum);
- sync_send();
+}
- // wait for the sync to finish sending
- serial_delay();
+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;
+}
- // read the middle of pulses
- _delay_us(SERIAL_DELAY/2);
+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
+}
- uint8_t checksum_computed = 0;
- for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
- serial_master_buffer[i] = serial_read_byte();
- sync_send();
- checksum_computed += serial_master_buffer[i];
+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)
+{
+ bits = (bits & 0x5) + (bits >> 1 & 0x5);
+ bits = (bits & 0x3) + (bits >> 2 & 0x3);
+ return 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;
}
- uint8_t checksum_received = serial_read_byte();
- sync_send();
+ serial_delay_half1();
- serial_input(); // end transaction
+ 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
- if ( checksum_computed != checksum_received ) {
- status |= SLAVE_DATA_CORRUPT;
+ // 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 {
- status &= ~SLAVE_DATA_CORRUPT;
+ *trans->status = TRANSACTION_ACCEPTED;
}
-}
-inline
-bool serial_slave_DATA_CORRUPT(void) {
- return status & SLAVE_DATA_CORRUPT;
+ sync_recv(); //weit initiator output to high
}
-// Copies the serial_slave_buffer to the master and sends the
-// serial_master_buffer to the slave.
+/////////
+// start transaction by initiator
+//
+// int soft_serial_transaction(int sstd_index)
//
// Returns:
-// 0 => no error
-// 1 => slave did not respond
-int serial_update_buffers(void) {
- // this code is very time dependent, so we need to disable interrupts
+// TRANSACTION_END
+// 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();
- // signal to the slave that we want to start a transaction
+ // signal to the target that we want to start a transaction
serial_output();
serial_low();
- _delay_us(1);
+ _delay_us(SLAVE_INT_WIDTH_US);
- // wait for the slaves response
- serial_input();
- serial_high();
- _delay_us(SERIAL_DELAY);
+#ifndef SERIAL_USE_MULTI_TRANSACTION
+ // wait for the target response
+ serial_input_with_pullup();
+ _delay_us(SLAVE_INT_RESPONSE_TIME);
- // check if the slave is present
+ // check if the target is present
if (serial_read_pin()) {
- // slave failed to pull the line low, assume not present
+ // target failed to pull the line low, assume not present
+ serial_output();
+ serial_high();
+ *trans->status = TRANSACTION_NO_RESPONSE;
sei();
- return 1;
+ return TRANSACTION_NO_RESPONSE;
}
- // if the slave is present syncronize with it
- sync_recv();
-
- uint8_t checksum_computed = 0;
- // receive data from the slave
- for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
- serial_slave_buffer[i] = serial_read_byte();
- sync_recv();
- checksum_computed += serial_slave_buffer[i];
+#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);
}
- uint8_t checksum_received = serial_read_byte();
- sync_recv();
- if (checksum_computed != checksum_received) {
- sei();
- return 1;
+ // 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
- uint8_t checksum = 0;
- // send data to the slave
- for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
- serial_write_byte(serial_master_buffer[i]);
- sync_recv();
- checksum += serial_master_buffer[i];
+ // 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);
}
- serial_write_byte(checksum);
- sync_recv();
// always, release the line when not in use
- serial_output();
- serial_high();
+ sync_send();
+ *trans->status = TRANSACTION_END;
sei();
- return 0;
+ return TRANSACTION_END;
}
-#endif /* SOFT_SERIAL_PIN */
+#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;;
+ sei();
+ return retval;
+}
+#endif
+
+#endif
+
+// Helix serial.c history
+// 2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc)
+// 2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4)
+// (adjusted with avr-gcc 4.9.2)
+// 2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78)
+// (adjusted with avr-gcc 4.9.2)
+// 2018-8-11 add support multi-type transaction (#3608, feb5e4aae)
+// (adjusted with avr-gcc 4.9.2)
+// 2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff)
+// (adjusted with avr-gcc 7.3.0)
+// 2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66)
+// (adjusted with avr-gcc 5.4.0, 7.3.0)
+// 2018-12-17 copy to TOP/quantum/split_common/ and remove backward compatibility code (#4669)
diff --git a/quantum/split_common/serial.h b/quantum/split_common/serial.h
index 0b99f352d..b6638b3bd 100644
--- a/quantum/split_common/serial.h
+++ b/quantum/split_common/serial.h
@@ -1,5 +1,5 @@
-#ifndef MY_SERIAL_H
-#define MY_SERIAL_H
+#ifndef SOFT_SERIAL_H
+#define SOFT_SERIAL_H
#include
@@ -7,20 +7,59 @@
// Need Soft Serial defines in config.h
// /////////////////////////////////////////////////////////////////
// ex.
-// /* Configuration of lower interface with the lower layer(hardware) of serial.c */
// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
+// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
+// // 1: about 137kbps (default)
+// // 2: about 75kbps
+// // 3: about 39kbps
+// // 4: about 26kbps
+// // 5: about 20kbps
//
-// /* Configuration of upper interface with the upper layer of serial.c */
-// #define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
-// #define SERIAL_MASTER_BUFFER_LENGTH 1
+// //// USE simple API (using signle-type transaction function)
+// /* nothing */
+// //// USE flexible API (using multi-type transaction function)
+// #define SERIAL_USE_MULTI_TRANSACTION
+//
+// /////////////////////////////////////////////////////////////////
-// Buffers for master - slave communication
-extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
-extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
+// Soft Serial Transaction Descriptor
+typedef struct _SSTD_t {
+ uint8_t *status;
+ uint8_t initiator2target_buffer_size;
+ uint8_t *initiator2target_buffer;
+ uint8_t target2initiator_buffer_size;
+ uint8_t *target2initiator_buffer;
+} SSTD_t;
+#define TID_LIMIT( table ) (sizeof(table) / sizeof(SSTD_t))
-void serial_master_init(void);
-void serial_slave_init(void);
-int serial_update_buffers(void);
-bool serial_slave_data_corrupt(void);
+// initiator is transaction start side
+void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
+// target is interrupt accept side
+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
+#ifndef SERIAL_USE_MULTI_TRANSACTION
+int soft_serial_transaction(void);
+#else
+int soft_serial_transaction(int sstd_index);
#endif
+
+// target status
+// *SSTD_t.status has
+// initiator:
+// TRANSACTION_END
+// or TRANSACTION_NO_RESPONSE
+// or TRANSACTION_DATA_ERROR
+// target:
+// TRANSACTION_DATA_ERROR
+// or TRANSACTION_ACCEPTED
+#define TRANSACTION_ACCEPTED 0x8
+#ifdef SERIAL_USE_MULTI_TRANSACTION
+int soft_serial_get_and_clean_status(int sstd_index);
+#endif
+
+#endif /* SOFT_SERIAL_H */
diff --git a/quantum/split_common/serial_backward_compatibility.h b/quantum/split_common/serial_backward_compatibility.h
deleted file mode 100644
index 216b6c41f..000000000
--- a/quantum/split_common/serial_backward_compatibility.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* serial.h backward compatibility */
-
-// #ifndef SOFT_SERIAL_PIN
-// #define SOFT_SERIAL_PIN D0
-// #endif
-
-#ifndef SERIAL_SLAVE_BUFFER_LENGTH
- #define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
- #define SERIAL_MASTER_BUFFER_LENGTH 1
-#endif
-
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 56077e4f2..e4475c535 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -11,9 +11,6 @@
#include "timer.h"
#include "split_flags.h"
-#ifdef RGBLIGHT_ENABLE
-# include "rgblight.h"
-#endif
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif
@@ -24,8 +21,6 @@
#if defined(USE_I2C) || defined(EH)
# include "i2c.h"
-#else
-# include "serial.h"
#endif
volatile bool isLeftHand = true;
@@ -112,7 +107,7 @@ void keyboard_slave_loop(void) {
BACKLIT_DIRTY = false;
}
#else // USE_SERIAL
- backlight_set(serial_master_buffer[SERIAL_BACKLIT_START]);
+ backlight_set(serial_m2s_buffer.backlight_level);
#endif
#endif
// Read RGB Info
@@ -137,7 +132,9 @@ void keyboard_slave_loop(void) {
sei();
}
#else // USE_SERIAL
+ #ifdef RGBLIGHT_SPLIT
// Add serial implementation for RGB here
+ #endif
#endif
#endif
}
diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h
index 45e8db0f2..d6cf3e72a 100644
--- a/quantum/split_common/split_util.h
+++ b/quantum/split_common/split_util.h
@@ -7,9 +7,6 @@
#include
#include "eeconfig.h"
-// backlight level store index in serial_master_buffer[] for slave to read
-#define SERIAL_BACKLIT_START 0x00
-
#define SLAVE_I2C_ADDRESS 0x32
extern volatile bool isLeftHand;
--
cgit v1.2.3-70-g09d2
From c0859ac096f1e4251351bb0a5a04b3ae4a9451f4 Mon Sep 17 00:00:00 2001
From: Danny
Date: Fri, 28 Dec 2018 16:02:53 -0500
Subject: Update split keyboard docs (#4735)
* Remove unused I2C_MASTER_RIGHT setting
* Update documentation about split keyboard options
---
docs/config_options.md | 37 +++++++++++++++++++++++++++++++++++--
quantum/split_common/serial.c | 2 +-
quantum/split_common/split_util.c | 3 +--
3 files changed, 37 insertions(+), 5 deletions(-)
(limited to 'quantum/split_common/serial.c')
diff --git a/docs/config_options.md b/docs/config_options.md
index 4bbc5debd..085ab3ee5 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -197,8 +197,27 @@ If you define these options you will enable the associated feature, which may in
Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk
-* `#define SPLIT_HAND_PIN B7`
- * For using high/low pin to determine handedness, low = right hand, high = left hand. Replace 'B7' with the pin you are using. This is optional and you can still use the EEHANDS method or MASTER_LEFT / MASTER_RIGHT defines like the stock Let's Split uses.
+### Setting Handedness
+
+One thing to remember, the side that the USB port is plugged into is always the master half. The side not plugged into USB is the slave.
+
+There are a few different ways to set handedness for split keyboards (listed in order of precedence):
+
+1. Set `SPLIT_HAND_PIN`: Reads a pin to determine handedness. If pin is high, it's the left side, if low, the half is determined to be the right side
+2. Set `EE_HANDS` and flash `eeprom-lefthand.eep`/`eeprom-righthand.eep` to each half
+3. Set `MASTER_RIGHT`: Half that is plugged into the USB port is determined to be the master and right half (inverse of the default)
+4. Default: The side that is plugged into the USB port is the master half and is assumed to be the left half. The slave side is the right half
+
+* `#define SPLIT_HAND_PIN B7`
+ * For using high/low pin to determine handedness, low = right hand, high = left hand. Replace `B7` with the pin you are using. This is optional, and if you leave `SPLIT_HAND_PIN` undefined, then you can still use the EE_HANDS method or MASTER_LEFT / MASTER_RIGHT defines like the stock Let's Split uses.
+
+* `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` is not defined)
+ * Reads the handedness value stored in the EEPROM after `eeprom-lefthand.eep`/`eeprom-righthand.eep` has been flashed to their respective halves.
+
+* `#define MASTER_RIGHT`
+ * Master half is defined to be the right half.
+
+### Other Options
* `#define USE_I2C`
* For using I2C instead of Serial (defaults to serial)
@@ -206,6 +225,20 @@ Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in yo
* `#define SOFT_SERIAL_PIN D0`
* When using serial, define this. `D0` or `D1`,`D2`,`D3`,`E6`.
+* `#define MATRIX_ROW_PINS_RIGHT { }`
+* `#define MATRIX_COL_PINS_RIGHT { }`
+ * If you want to specify a different pinout for the right half than the left half, you can define `MATRIX_ROW_PINS_RIGHT`/`MATRIX_COL_PINS_RIGHT`. Currently, the size of `MATRIX_ROW_PINS` must be the same as `MATRIX_ROW_PINS_RIGHT` and likewise for the definition of columns.
+
+* `#define SELECT_SOFT_SERIAL_SPEED ` (default speed is 1)
+ * Sets the protocol speed when using serial communication
+ * Speeds:
+ * 0: about 189kbps (Experimental only)
+ * 1: about 137kbps (default)
+ * 2: about 75kbps
+ * 3: about 39kbps
+ * 4: about 26kbps
+ * 5: about 20kbps
+
# The `rules.mk` File
This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features.
diff --git a/quantum/split_common/serial.c b/quantum/split_common/serial.c
index 4df8d103b..1315377a3 100644
--- a/quantum/split_common/serial.c
+++ b/quantum/split_common/serial.c
@@ -90,7 +90,7 @@
#ifndef SELECT_SOFT_SERIAL_SPEED
#define SELECT_SOFT_SERIAL_SPEED 1
-// 0: about 189kbps (Experiment only)
+// 0: about 189kbps (Experimental only)
// 1: about 137kbps (default)
// 2: about 75kbps
// 3: about 39kbps
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index e4475c535..da04c8d3f 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -36,8 +36,7 @@ static void setup_handedness(void) {
#ifdef EE_HANDS
isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
#else
- // I2C_MASTER_RIGHT is deprecated, use MASTER_RIGHT instead, since this works for both serial and i2c
- #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT)
+ #ifdef(MASTER_RIGHT)
isLeftHand = !has_usb();
#else
isLeftHand = has_usb();
--
cgit v1.2.3-70-g09d2