From 90b086137c816fb72ef3a5fb2ee5c424d96bb006 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 26 Jun 2020 19:12:00 -0700 Subject: [PATCH 1/8] Remove use of ATMEGA32U4_KEYBOARD macro for the Atreus Trying to get back to code rather than macros --- src/kaleidoscope/device/keyboardio/Atreus2.h | 23 +++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.h b/src/kaleidoscope/device/keyboardio/Atreus2.h index db8082c7..7d181caa 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.h +++ b/src/kaleidoscope/device/keyboardio/Atreus2.h @@ -29,11 +29,24 @@ namespace kaleidoscope { namespace device { namespace keyboardio { -ATMEGA32U4_KEYBOARD( - Atreus, Caterina, "atreus", - ROW_PIN_LIST({PIN_F6, PIN_F5, PIN_F4, PIN_F1}), - COL_PIN_LIST({PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2}) -); + + ATMEGA32U4_DEVICE_PROPS(Atreus, Caterina, "atreus", + ROW_PIN_LIST({PIN_F6, PIN_F5, PIN_F4, PIN_F1}), + COL_PIN_LIST({PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2})); + +#ifndef KALEIDOSCOPE_VIRTUAL_BUILD + ATMEGA32U4_DEVICE(Atreus) + +#else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD + /* Device definition omitted for virtual device builds. + * We need to forward declare the device name, though, as there are + * some legacy extern references to boards whose definition + * depends on this. + */ + class Atreus; + +#endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD + #define PER_KEY_DATA(dflt, \ R0C0, R0C1, R0C2, R0C3, R0C4, R0C7, R0C8, R0C9, R0C10, R0C11, \ From 521fea77ee2706d887abcef2f8f5f1ca4815524e Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 26 Jun 2020 19:15:31 -0700 Subject: [PATCH 2/8] Atreus: remove use of ATMEGA32U4_DEVICE macro --- src/kaleidoscope/device/keyboardio/Atreus2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.h b/src/kaleidoscope/device/keyboardio/Atreus2.h index 7d181caa..64e3d38e 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.h +++ b/src/kaleidoscope/device/keyboardio/Atreus2.h @@ -35,7 +35,7 @@ namespace keyboardio { COL_PIN_LIST({PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2})); #ifndef KALEIDOSCOPE_VIRTUAL_BUILD - ATMEGA32U4_DEVICE(Atreus) + class Atreus: public kaleidoscope::device::ATmega32U4Keyboard {}; #else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD /* Device definition omitted for virtual device builds. From 4f45ec13d74b2040a173c76ea6330c5f8c077c96 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 26 Jun 2020 19:21:10 -0700 Subject: [PATCH 3/8] Remove use of ATMEGA32U4_DEVICE_PROPS for Atreus --- src/kaleidoscope/device/keyboardio/Atreus2.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.h b/src/kaleidoscope/device/keyboardio/Atreus2.h index 64e3d38e..c62d966e 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.h +++ b/src/kaleidoscope/device/keyboardio/Atreus2.h @@ -30,9 +30,16 @@ namespace device { namespace keyboardio { - ATMEGA32U4_DEVICE_PROPS(Atreus, Caterina, "atreus", - ROW_PIN_LIST({PIN_F6, PIN_F5, PIN_F4, PIN_F1}), - COL_PIN_LIST({PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2})); + struct AtreusProps : kaleidoscope::device::ATmega32U4KeyboardProps { + struct KeyScannerProps : public kaleidoscope::driver::keyscanner::ATmegaProps { + ATMEGA_KEYSCANNER_PROPS( + ROW_PIN_LIST({PIN_F6, PIN_F5, PIN_F4, PIN_F1}), + COL_PIN_LIST({PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2})); + }; + typedef kaleidoscope::driver::keyscanner::ATmega KeyScanner; + typedef kaleidoscope::driver::bootloader::avr::Caterina BootLoader; + static constexpr const char *short_name = "atreus"; + }; #ifndef KALEIDOSCOPE_VIRTUAL_BUILD class Atreus: public kaleidoscope::device::ATmega32U4Keyboard {}; From 499f0fca3a0243cb8c19193aa8951b9f218bd9af Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 26 Jun 2020 19:56:54 -0700 Subject: [PATCH 4/8] Atreus2: remove use of ATMEGA_KEYSCANNER_PROPS --- src/kaleidoscope/device/keyboardio/Atreus2.h | 21 ++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.h b/src/kaleidoscope/device/keyboardio/Atreus2.h index c62d966e..9f662692 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.h +++ b/src/kaleidoscope/device/keyboardio/Atreus2.h @@ -32,18 +32,23 @@ namespace keyboardio { struct AtreusProps : kaleidoscope::device::ATmega32U4KeyboardProps { struct KeyScannerProps : public kaleidoscope::driver::keyscanner::ATmegaProps { - ATMEGA_KEYSCANNER_PROPS( - ROW_PIN_LIST({PIN_F6, PIN_F5, PIN_F4, PIN_F1}), - COL_PIN_LIST({PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2})); - }; - typedef kaleidoscope::driver::keyscanner::ATmega KeyScanner; - typedef kaleidoscope::driver::bootloader::avr::Caterina BootLoader; - static constexpr const char *short_name = "atreus"; + + static constexpr uint8_t matrix_rows = 4; + static constexpr uint8_t matrix_columns = 12; + typedef MatrixAddr KeyAddr; +#ifndef KALEIDOSCOPE_VIRTUAL_BUILD + static constexpr uint8_t matrix_row_pins[matrix_rows] = {PIN_F6, PIN_F5, PIN_F4, PIN_F1}; + static constexpr uint8_t matrix_col_pins[matrix_columns] = {PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2}; +#endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD + }; + + typedef kaleidoscope::driver::keyscanner::ATmega KeyScanner; + typedef kaleidoscope::driver::bootloader::avr::Caterina BootLoader; + static constexpr const char *short_name = "atreus"; }; #ifndef KALEIDOSCOPE_VIRTUAL_BUILD class Atreus: public kaleidoscope::device::ATmega32U4Keyboard {}; - #else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD /* Device definition omitted for virtual device builds. * We need to forward declare the device name, though, as there are From 6b44b4ff8df20a7c2ee618c6ee4cd485d97c414c Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 26 Jun 2020 20:08:14 -0700 Subject: [PATCH 5/8] Remove use of ATMEGA_KEYSCANNER_BOILERPLATE for Atreus2 --- src/kaleidoscope/device/keyboardio/Atreus2.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.cpp b/src/kaleidoscope/device/keyboardio/Atreus2.cpp index 5a0ad92d..b13fe48d 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.cpp +++ b/src/kaleidoscope/device/keyboardio/Atreus2.cpp @@ -25,8 +25,18 @@ namespace kaleidoscope { namespace device { namespace keyboardio { - -ATMEGA_KEYSCANNER_BOILERPLATE + const uint8_t kaleidoscope::Device::KeyScannerProps::matrix_rows; + const uint8_t kaleidoscope::Device::KeyScannerProps::matrix_columns; + constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_row_pins[matrix_rows]; + constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_col_pins[matrix_columns]; + template<> uint16_t kaleidoscope::Device::KeyScanner::previousKeyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; + template<> uint16_t kaleidoscope::Device::KeyScanner::keyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; + template<> uint16_t kaleidoscope::Device::KeyScanner::masks_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; + template<> uint8_t kaleidoscope::Device::KeyScanner::debounce_matrix_[kaleidoscope::Device::KeyScannerProps::matrix_rows][kaleidoscope::Device::KeyScannerProps::matrix_columns] = {}; + + ISR(TIMER1_OVF_vect) { + Runtime.device().keyScanner().do_scan_ = true; + } } } From 058ce5c42c3427f5ec41da4c4cad3437e276a8fd Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 26 Jun 2020 20:28:00 -0700 Subject: [PATCH 6/8] astyle --- .../device/keyboardio/Atreus2.cpp | 24 ++++++------ src/kaleidoscope/device/keyboardio/Atreus2.h | 38 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.cpp b/src/kaleidoscope/device/keyboardio/Atreus2.cpp index b13fe48d..3daa5a8b 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.cpp +++ b/src/kaleidoscope/device/keyboardio/Atreus2.cpp @@ -25,18 +25,18 @@ namespace kaleidoscope { namespace device { namespace keyboardio { - const uint8_t kaleidoscope::Device::KeyScannerProps::matrix_rows; - const uint8_t kaleidoscope::Device::KeyScannerProps::matrix_columns; - constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_row_pins[matrix_rows]; - constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_col_pins[matrix_columns]; - template<> uint16_t kaleidoscope::Device::KeyScanner::previousKeyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; - template<> uint16_t kaleidoscope::Device::KeyScanner::keyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; - template<> uint16_t kaleidoscope::Device::KeyScanner::masks_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; - template<> uint8_t kaleidoscope::Device::KeyScanner::debounce_matrix_[kaleidoscope::Device::KeyScannerProps::matrix_rows][kaleidoscope::Device::KeyScannerProps::matrix_columns] = {}; - - ISR(TIMER1_OVF_vect) { - Runtime.device().keyScanner().do_scan_ = true; - } +const uint8_t kaleidoscope::Device::KeyScannerProps::matrix_rows; +const uint8_t kaleidoscope::Device::KeyScannerProps::matrix_columns; +constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_row_pins[matrix_rows]; +constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_col_pins[matrix_columns]; +template<> uint16_t kaleidoscope::Device::KeyScanner::previousKeyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; +template<> uint16_t kaleidoscope::Device::KeyScanner::keyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; +template<> uint16_t kaleidoscope::Device::KeyScanner::masks_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; +template<> uint8_t kaleidoscope::Device::KeyScanner::debounce_matrix_[kaleidoscope::Device::KeyScannerProps::matrix_rows][kaleidoscope::Device::KeyScannerProps::matrix_columns] = {}; + +ISR(TIMER1_OVF_vect) { + Runtime.device().keyScanner().do_scan_ = true; +} } } diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.h b/src/kaleidoscope/device/keyboardio/Atreus2.h index 9f662692..5b2659c2 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.h +++ b/src/kaleidoscope/device/keyboardio/Atreus2.h @@ -30,32 +30,32 @@ namespace device { namespace keyboardio { - struct AtreusProps : kaleidoscope::device::ATmega32U4KeyboardProps { - struct KeyScannerProps : public kaleidoscope::driver::keyscanner::ATmegaProps { +struct AtreusProps : kaleidoscope::device::ATmega32U4KeyboardProps { + struct KeyScannerProps : public kaleidoscope::driver::keyscanner::ATmegaProps { - static constexpr uint8_t matrix_rows = 4; - static constexpr uint8_t matrix_columns = 12; - typedef MatrixAddr KeyAddr; + static constexpr uint8_t matrix_rows = 4; + static constexpr uint8_t matrix_columns = 12; + typedef MatrixAddr KeyAddr; #ifndef KALEIDOSCOPE_VIRTUAL_BUILD - static constexpr uint8_t matrix_row_pins[matrix_rows] = {PIN_F6, PIN_F5, PIN_F4, PIN_F1}; - static constexpr uint8_t matrix_col_pins[matrix_columns] = {PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2}; + static constexpr uint8_t matrix_row_pins[matrix_rows] = {PIN_F6, PIN_F5, PIN_F4, PIN_F1}; + static constexpr uint8_t matrix_col_pins[matrix_columns] = {PIN_F7, PIN_E2, PIN_C7, PIN_C6, PIN_B6, PIN_B5, PIN_D7, PIN_D6, PIN_D4, PIN_D5, PIN_D3, PIN_D2}; #endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD - }; - - typedef kaleidoscope::driver::keyscanner::ATmega KeyScanner; - typedef kaleidoscope::driver::bootloader::avr::Caterina BootLoader; - static constexpr const char *short_name = "atreus"; }; + typedef kaleidoscope::driver::keyscanner::ATmega KeyScanner; + typedef kaleidoscope::driver::bootloader::avr::Caterina BootLoader; + static constexpr const char *short_name = "atreus"; +}; + #ifndef KALEIDOSCOPE_VIRTUAL_BUILD - class Atreus: public kaleidoscope::device::ATmega32U4Keyboard {}; +class Atreus: public kaleidoscope::device::ATmega32U4Keyboard {}; #else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD - /* Device definition omitted for virtual device builds. - * We need to forward declare the device name, though, as there are - * some legacy extern references to boards whose definition - * depends on this. - */ - class Atreus; +/* Device definition omitted for virtual device builds. + * We need to forward declare the device name, though, as there are + * some legacy extern references to boards whose definition + * depends on this. + */ +class Atreus; #endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD From 4f1929b0430fd9d564b297af638af008c27d892f Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 29 Jun 2020 12:55:54 +0200 Subject: [PATCH 7/8] keyboardio/Atreus: Simplify the hardware plugin a bit The `kaleidoscope::Device` aliases are there for use-cases that need to be device agnostic, we do not need to use them in the hardware plugin itself, because that plugin _is_ very much tied to the device. We can just use the device specific original names. To make things shorter, we can also set up a pair of aliases for `KeyScannerProps` and `KeyScanner`, to make the declarations even shorter. Signed-off-by: Gergely Nagy --- .../device/keyboardio/Atreus2.cpp | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.cpp b/src/kaleidoscope/device/keyboardio/Atreus2.cpp index 3daa5a8b..1bf38642 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.cpp +++ b/src/kaleidoscope/device/keyboardio/Atreus2.cpp @@ -22,17 +22,25 @@ #include "kaleidoscope/Runtime.h" #include "kaleidoscope/driver/keyscanner/Base_Impl.h" +using namespace kaleidoscope::device::keyboardio; + +using KeyScannerProps = typename AtreusProps::KeyScannerProps; +using KeyScanner = typename AtreusProps::KeyScanner; + namespace kaleidoscope { namespace device { namespace keyboardio { -const uint8_t kaleidoscope::Device::KeyScannerProps::matrix_rows; -const uint8_t kaleidoscope::Device::KeyScannerProps::matrix_columns; -constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_row_pins[matrix_rows]; -constexpr uint8_t kaleidoscope::Device::KeyScannerProps::matrix_col_pins[matrix_columns]; -template<> uint16_t kaleidoscope::Device::KeyScanner::previousKeyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; -template<> uint16_t kaleidoscope::Device::KeyScanner::keyState_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; -template<> uint16_t kaleidoscope::Device::KeyScanner::masks_[kaleidoscope::Device::KeyScannerProps::matrix_rows] = {}; -template<> uint8_t kaleidoscope::Device::KeyScanner::debounce_matrix_[kaleidoscope::Device::KeyScannerProps::matrix_rows][kaleidoscope::Device::KeyScannerProps::matrix_columns] = {}; + +const uint8_t KeyScannerProps::matrix_rows; +const uint8_t KeyScannerProps::matrix_columns; + +constexpr uint8_t KeyScannerProps::matrix_row_pins[matrix_rows]; +constexpr uint8_t KeyScannerProps::matrix_col_pins[matrix_columns]; + +template<> uint16_t KeyScanner::previousKeyState_[KeyScannerProps::matrix_rows] = {}; +template<> uint16_t KeyScanner::keyState_[KeyScannerProps::matrix_rows] = {}; +template<> uint16_t KeyScanner::masks_[KeyScannerProps::matrix_rows] = {}; +template<> uint8_t KeyScanner::debounce_matrix_[KeyScannerProps::matrix_rows][KeyScannerProps::matrix_columns] = {}; ISR(TIMER1_OVF_vect) { Runtime.device().keyScanner().do_scan_ = true; From b27433f9ee428ab1713f9efc0d3226f6743ab74e Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 29 Jun 2020 21:29:42 +0200 Subject: [PATCH 8/8] keyboardio/Atreus: Add some explanatory comments While the code became shorter with the previous commit, it did not become much easier to understand and follow. Some of the choices made weren't self explanatory. For that reason, lets put comments around the relevant parts, that explain why we've done it that way. Signed-off-by: Gergely Nagy --- .../device/keyboardio/Atreus2.cpp | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/kaleidoscope/device/keyboardio/Atreus2.cpp b/src/kaleidoscope/device/keyboardio/Atreus2.cpp index 1bf38642..d5eb707f 100644 --- a/src/kaleidoscope/device/keyboardio/Atreus2.cpp +++ b/src/kaleidoscope/device/keyboardio/Atreus2.cpp @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- * Keyboardio Atreus hardware support for Kaleidoscope - * Copyright (C) 2019 Keyboard.io, Inc + * Copyright (C) 2019, 2020 Keyboard.io, Inc * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,8 +22,11 @@ #include "kaleidoscope/Runtime.h" #include "kaleidoscope/driver/keyscanner/Base_Impl.h" +// We're using the `kaleidoscope::device::keyboardio` namespace, and set up the +// aliases here, so that they're in the global namespace, within the scope of +// this file. We do that, because of how templates are resolved and evaluated, +// see more just down below! using namespace kaleidoscope::device::keyboardio; - using KeyScannerProps = typename AtreusProps::KeyScannerProps; using KeyScanner = typename AtreusProps::KeyScanner; @@ -31,17 +34,34 @@ namespace kaleidoscope { namespace device { namespace keyboardio { +// `KeyScannerProps` here refers to the alias set up above. We do not need to +// prefix the `matrix_rows` and `matrix_columns` names within the array +// declaration, because those are resolved within the context of the class, so +// the `matrix_rows` in `KeyScannerProps::matrix_row_pins[matrix_rows]` gets +// resolved as `KeyScannerProps::matrix_rows`. const uint8_t KeyScannerProps::matrix_rows; const uint8_t KeyScannerProps::matrix_columns; - constexpr uint8_t KeyScannerProps::matrix_row_pins[matrix_rows]; constexpr uint8_t KeyScannerProps::matrix_col_pins[matrix_columns]; +// Resolving is a bit different in case of templates, however: the name of the +// array is resolved within the scope of the namespace and the class, but the +// array size is not - because it is a template. Therefore, we need a fully +// qualified name there - or an alias in the global scope, which we set up just +// above. template<> uint16_t KeyScanner::previousKeyState_[KeyScannerProps::matrix_rows] = {}; template<> uint16_t KeyScanner::keyState_[KeyScannerProps::matrix_rows] = {}; template<> uint16_t KeyScanner::masks_[KeyScannerProps::matrix_rows] = {}; template<> uint8_t KeyScanner::debounce_matrix_[KeyScannerProps::matrix_rows][KeyScannerProps::matrix_columns] = {}; +// We set up the TIMER1 interrupt vector here. Due to dependency reasons, this +// cannot be in a header-only driver, and must be placed here. +// +// Timer1 is responsible for setting a property on the KeyScanner, which will +// tell it to do a scan. We use this to make sure that scans happen at roughly +// the intervals we want. We do the scan outside of the interrupt scope for +// practical reasons: guarding every codepath against interrupts that can be +// reached from the scan is far too tedious, for very little gain. ISR(TIMER1_OVF_vect) { Runtime.device().keyScanner().do_scan_ = true; }