diff options
author | Jay Greco <[email protected]> | 2020-10-22 23:47:14 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2020-10-23 17:47:14 +1100 |
commit | 999326acc81687794e25ad7731f37da59881e0ca (patch) | |
tree | ceb786ae2dac25486a57c5ed004e921677c922b1 /keyboards/nullbitsco/nibble/remote_kb.c | |
parent | 8cbaea9e8d00b959ccb1b474fa8a81417b651de2 (diff) | |
download | qmk_firmware-999326acc81687794e25ad7731f37da59881e0ca.tar.gz qmk_firmware-999326acc81687794e25ad7731f37da59881e0ca.zip |
Add nullbits nibble (#9250)
* Add NIBBLE keyboard
* Update VID for VIA compatibility
* Add QMK PR feedback
* Update matrix_init_remote_kb()
* Update with requested changes
Clean up config, makefile rules, and keymap files
* Update with changes for unified ANSI/ISO layout
* Add NO_USB_STARTUP_CHECK note in readme
* Add license info, update with PR changes
-Refactor encoder, via_extras code
-Refactor VIA specific code to live in keymap folder
-Remove non-inclusive naming in remote keyboard.c/h
-Add documentation to remote_keyboard.c
-Add compiler check for vusb_detect for non-avr micros
* Fix print formatter in encoder handler
Co-authored-by: Nick Brassel <[email protected]>
* Small PR updates
-Remove unneded matrix code from nibble.c
-Clean up include code in nibble_encoder.h
* Update Big LED headerfile
-Declare Big LED functions in header file (derp)
* Update keyboards/nullbitsco/nibble/nibble.c
-Update with drashna's suggested CAPS LED code change
Co-authored-by: Drashna Jaelre <[email protected]>
* Update keyboards/nullbitsco/nibble/rules.mk
-Update with drasha's suggested makefile formatting changes
Co-authored-by: Drashna Jaelre <[email protected]>
* Fix caps_lock typo
Co-authored-by: Nick Brassel <[email protected]>
Co-authored-by: Drashna Jaelre <[email protected]>
Diffstat (limited to 'keyboards/nullbitsco/nibble/remote_kb.c')
-rw-r--r-- | keyboards/nullbitsco/nibble/remote_kb.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/keyboards/nullbitsco/nibble/remote_kb.c b/keyboards/nullbitsco/nibble/remote_kb.c new file mode 100644 index 0000000000..2e36f5f22e --- /dev/null +++ b/keyboards/nullbitsco/nibble/remote_kb.c @@ -0,0 +1,177 @@ +/* Copyright 2020 Jay Greco + * + * 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 + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* +Remote keyboard is an experimental feature that allows for connecting another +keyboard, macropad, numpad, or accessory without requiring an additional USB connection. +The "remote keyboard" forwards its keystrokes using UART serial over TRRS. Dynamic VUSB +detect allows the keyboard automatically switch to host or remote mode depending on +which is connected to the USB port. + +Possible functionality includes the ability to send data from the host to the remote using +a reverse link, allowing for LED sync, configuration, and more data sharing between devices. +This will require a new communication protocol, as the current one is limited. +*/ + +#include "remote_kb.h" + +uint8_t + msg[UART_MSG_LEN], + msg_idx = 0; + +bool + is_host = true; + +// Private functions + +static bool vbus_detect(void) { + #if defined(__AVR_ATmega32U4__) + //returns true if VBUS is present, false otherwise. + USBCON |= (1 << OTGPADE); //enables VBUS pad + _delay_us(10); + return (USBSTA & (1<<VBUS)); //checks state of VBUS + #else + #error vbus_detect is not implemented for this architecure! + #endif +} + +static uint8_t chksum8(const unsigned char *buf, size_t len) { + unsigned int sum; + for (sum = 0 ; len != 0 ; len--) + sum += *(buf++); + return (uint8_t)sum; +} + +static void send_msg(uint16_t keycode, bool pressed) { + msg[IDX_PREAMBLE] = UART_PREAMBLE; + msg[IDX_KCLSB] = (keycode & 0xFF); + msg[IDX_KCMSB] = (keycode >> 8) & 0xFF; + msg[IDX_PRESSED] = pressed; + msg[IDX_CHECKSUM] = chksum8(msg, UART_MSG_LEN-1); + + for (int i=0; i<UART_MSG_LEN; i++) { + uart_putchar(msg[i]); + } +} + +static void print_message_buffer(void) { + for (int i=0; i<UART_MSG_LEN; i++) { + dprintf("msg[%u]: %u\n", i, msg[i]); + } +} + +static void process_uart(void) { + uint8_t chksum = chksum8(msg, UART_MSG_LEN-1); + if (msg[IDX_PREAMBLE] != UART_PREAMBLE || msg[IDX_CHECKSUM] != chksum) { + dprintf("UART checksum mismatch!\n"); + print_message_buffer(); + dprintf("calc checksum: %u\n", chksum); + } else { + uint16_t keycode = (uint16_t)msg[IDX_KCLSB] | ((uint16_t)msg[IDX_KCMSB] << 8); + bool pressed = (bool)msg[IDX_PRESSED]; + if (IS_RM_KC(keycode)) { + keyrecord_t record; + record.event.pressed = pressed; + if (pressed) dprintf("Remote macro: press [%u]\n", keycode); + else dprintf("Remote macro: release [%u]\n", keycode); + process_record_user(keycode, &record); + } else { + if (pressed) { + dprintf("Remote: press [%u]\n", keycode); + register_code(keycode); + } else { + dprintf("Remote: release [%u]\n", keycode); + unregister_code(keycode); + } + } + } +} + +static void get_msg(void) { + while (uart_available()) { + msg[msg_idx] = uart_getchar(); + dprintf("idx: %u, recv: %u\n", msg_idx, msg[msg_idx]); + if (msg_idx == 0 && (msg[msg_idx] != UART_PREAMBLE)) { + dprintf("Byte sync error!\n"); + msg_idx = 0; + } else if (msg_idx == (UART_MSG_LEN-1)) { + process_uart(); + msg_idx = 0; + } else { + msg_idx++; + } + } +} + +static void handle_host_incoming(void) { + get_msg(); +} + +static void handle_host_outgoing(void) { + // for future reverse link use +} + +static void handle_remote_incoming(void) { + // for future reverse link use +} + +static void handle_remote_outgoing(uint16_t keycode, keyrecord_t *record) { + if (IS_HID_KC(keycode) || IS_RM_KC(keycode)) { + dprintf("Remote: send [%u]\n", keycode); + send_msg(keycode, record->event.pressed); + } +} + +// Public functions + +void matrix_init_remote_kb(void) { + uart_init(SERIAL_UART_BAUD); + is_host = vbus_detect(); +} + +void process_record_remote_kb(uint16_t keycode, keyrecord_t *record) { + #if defined (KEYBOARD_HOST) + handle_host_outgoing(); + + #elif defined(KEYBOARD_REMOTE) + handle_remote_outgoing(keycode, record); + + #else //auto check with VBUS + if (is_host) { + handle_host_outgoing(); + } + else { + handle_remote_outgoing(keycode, record); + } + #endif +} + +void matrix_scan_remote_kb(void) { + #if defined(KEYBOARD_HOST) + handle_host_incoming(); + + #elif defined (KEYBOARD_REMOTE) + handle_remote_incoming(); + + #else //auto check with VBUS + if (is_host) { + handle_host_incoming(); + } + else { + handle_remote_incoming(); + } + #endif +} |