Files

114 lines
2.7 KiB
C

// Copyright 2017, 2022 Joseph Wasson, Vladislav Kucheriavykh
// SPDX-License-Identifier: GPL-2.0-or-later
#include "steno.h"
#include "progmem.h"
#ifdef VIRTSER_ENABLE
# include "virtser.h"
#endif
#define TXB_NUL 0
#define TXB_S_L 0b00000001
#define TXB_T_L 0b00000010
#define TXB_K_L 0b00000100
#define TXB_P_L 0b00001000
#define TXB_W_L 0b00010000
#define TXB_H_L 0b00100000
#define TXB_R_L 0b01000001
#define TXB_A_L 0b01000010
#define TXB_O_L 0b01000100
#define TXB_STR 0b01001000
#define TXB_E_R 0b01010000
#define TXB_U_R 0b01100000
#define TXB_F_R 0b10000001
#define TXB_R_R 0b10000010
#define TXB_P_R 0b10000100
#define TXB_B_R 0b10001000
#define TXB_L_R 0b10010000
#define TXB_G_R 0b10100000
#define TXB_T_R 0b11000001
#define TXB_S_R 0b11000010
#define TXB_D_R 0b11000100
#define TXB_Z_R 0b11001000
#define TXB_NUM 0b11010000
#define TXB_GRP0 0b00000000
#define TXB_GRP1 0b01000000
#define TXB_GRP2 0b10000000
#define TXB_GRP3 0b11000000
#define TXB_GRPMASK 0b11000000
#define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6)
// clang-format off
static const uint8_t boltmap[64] PROGMEM = {
TXB_NUL,
TXB_NUM,
TXB_NUM,
TXB_NUM,
TXB_NUM,
TXB_NUM,
TXB_NUM,
TXB_S_L,
TXB_S_L,
TXB_T_L,
TXB_K_L,
TXB_P_L,
TXB_W_L,
TXB_H_L,
TXB_R_L,
TXB_A_L,
TXB_O_L,
TXB_STR,
TXB_STR,
TXB_NUL,
TXB_NUL,
TXB_NUL,
TXB_STR,
TXB_STR,
TXB_E_R,
TXB_U_R,
TXB_F_R,
TXB_R_R,
TXB_P_R,
TXB_B_R,
TXB_L_R,
TXB_G_R,
TXB_T_R,
TXB_S_R,
TXB_D_R,
TXB_NUM,
TXB_NUM,
TXB_NUM,
TXB_NUM,
TXB_NUM,
TXB_NUM,
TXB_Z_R,
};
// clang-format on
void steno_add_key_to_chord_bolt(uint8_t chord[MAX_STROKE_SIZE], uint8_t key) {
uint8_t boltcode = pgm_read_byte(boltmap + key);
chord[TXB_GET_GROUP(boltcode)] |= boltcode;
}
void steno_send_chord_bolt(uint8_t chord[MAX_STROKE_SIZE]) {
#ifdef VIRTSER_ENABLE
for (uint8_t i = 0; i < BOLT_STROKE_SIZE; ++i) {
// TX Bolt uses variable length packets where each byte corresponds to a bit array of certain keys.
// If a user chorded the keys of the first group with keys of the last group, for example, there
// would be bytes of 0x00 in `chord` for the middle groups which we mustn't send.
if (chord[i]) {
virtser_send(chord[i]);
}
}
// Sending a null packet is not always necessary, but it is simpler and more reliable
// to unconditionally send it every time instead of keeping track of more states and
// creating more branches in the execution of the program.
virtser_send(0);
#else
# pragma message "VIRTSER_ENABLE = yes is required for TX Bolt to work properly out of the box!"
#endif // VIRTSER_ENABLE
}