From 8d8856c6e0bcd4e77659db6a7ef36f16a6300529 Mon Sep 17 00:00:00 2001 From: heiso Date: Wed, 13 Nov 2024 14:15:54 +0100 Subject: [PATCH] wip: split firmware code --- firmware/Core/Inc/keyboard.h | 120 +++++++++ firmware/Core/Inc/main.h | 103 +------- firmware/Core/Src/keyboard.c | 427 +++++++++++++++++++++++++++++++ firmware/Core/Src/main.c | 476 +++-------------------------------- 4 files changed, 589 insertions(+), 537 deletions(-) create mode 100644 firmware/Core/Inc/keyboard.h create mode 100644 firmware/Core/Src/keyboard.c diff --git a/firmware/Core/Inc/keyboard.h b/firmware/Core/Inc/keyboard.h new file mode 100644 index 0000000..76efa6e --- /dev/null +++ b/firmware/Core/Inc/keyboard.h @@ -0,0 +1,120 @@ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __KEYBOARD_H +#define __KEYBOARD_H + +#define CALIBRATION_CYCLES 20 + +#define DEFAULT_TRIGGER_OFFSET 64 +#define DEFAULT_RESET_THRESHOLD 3 +#define DEFAULT_RAPID_TRIGGER_OFFSET 40 +#define DEFAULT_SCREAMING_VELOCITY_TRIGGER 45 +#define DEFAULT_TAP_TIMEOUT 200 + +#define IDLE_VALUE_APPROX 1800 +#define MAX_DISTANCE_APPROX 500 +#define IDLE_VALUE_OFFSET 10 +#define MAX_DISTANCE_OFFSET 60 +#define IDLE_CYCLES_UNTIL_SLEEP 15 + +#define ADC_CHANNEL_COUNT 5 +#define AMUX_SELECT_PINS_COUNT 4 +#define AMUX_CHANNEL_COUNT 16 + +#define MATRIX_ROWS 5 +#define MATRIX_COLS 15 + +#define XXXX 0xff +#define ____ 0x00 + +#define SPECIAL(X) (0b1000000000000000 | X) + +struct __attribute__((__packed__)) calibration { + uint16_t cycles_count; + uint16_t idle_value; + uint16_t max_distance; +}; + +enum direction { + GOING_UP, + GOING_DOWN, +}; + +struct __attribute__((__packed__)) state { + uint16_t value; + uint16_t distance; + uint8_t distance_8bits; + float filtered_distance; + int8_t velocity; + uint8_t filtered_distance_8bits; +}; + +enum actuation_status { + STATUS_MIGHT_BE_TAP, + STATUS_TAP, + STATUS_TRIGGERED, + STATUS_RESET, + STATUS_RAPID_TRIGGER_RESET +}; + +struct __attribute__((__packed__)) actuation { + enum direction direction; + uint8_t direction_changed_point; + enum actuation_status status; + uint8_t reset_offset; + uint8_t trigger_offset; + uint8_t rapid_trigger_offset; + uint8_t is_continuous_rapid_trigger_enabled; + uint32_t triggered_at; +}; + +enum key_type { + KEY_TYPE_EMPTY, + KEY_TYPE_NORMAL, + KEY_TYPE_MODIFIER, + KEY_TYPE_CONSUMER_CONTROL, +}; + +struct __attribute__((__packed__)) layer { + enum key_type type; + uint16_t value; +}; + +enum { + _BASE_LAYER, + _TAP_LAYER, + LAYERS_COUNT +}; + +struct __attribute__((__packed__)) key { + uint8_t is_enabled; + uint8_t row; + uint8_t column; + uint8_t idle_counter; + uint8_t is_idle; + struct layer layers[LAYERS_COUNT]; + struct calibration calibration; + struct state state; + struct actuation actuation; +}; + +struct user_config { + uint8_t trigger_offset; + uint8_t reset_threshold; + uint8_t rapid_trigger_offset; + uint8_t screaming_velocity_trigger; + uint16_t tap_timeout; + uint16_t keymaps[LAYERS_COUNT][MATRIX_ROWS][MATRIX_COLS]; +}; + +struct user_config keyboard_user_config; +static void keyboard_task(); +static void keyboard_init_keys(); +static void keyboard_read_config(); +static uint8_t keyboard_write_config(uint8_t *buffer, uint16_t offset, uint16_t size); +static void keyboard_select_amux(uint8_t amux_channel); +static void keyboard_select_adc(uint8_t adc_channel); +static uint16_t keyboard_read_adc(); +static void keyboard_close_adc(); +static uint32_t keyboard_get_time(); + +#endif /* __KEYBOARD_H */ diff --git a/firmware/Core/Inc/main.h b/firmware/Core/Inc/main.h index b909646..5223ce6 100644 --- a/firmware/Core/Inc/main.h +++ b/firmware/Core/Inc/main.h @@ -33,112 +33,11 @@ extern "C" { /* USER CODE BEGIN Includes */ #define CONFIG_ADDRESS 0x08040000 -#define CALIBRATION_CYCLES 20 - -#define DEFAULT_TRIGGER_OFFSET 64 -#define DEFAULT_RESET_THRESHOLD 3 -#define DEFAULT_RAPID_TRIGGER_OFFSET 40 -#define DEFAULT_SCREAMING_VELOCITY_TRIGGER 45 -#define DEFAULT_TAP_TIMEOUT 200 - -#define IDLE_VALUE_APPROX 1800 -#define MAX_DISTANCE_APPROX 500 -#define IDLE_VALUE_OFFSET 10 -#define MAX_DISTANCE_OFFSET 60 -#define IDLE_CYCLES_UNTIL_SLEEP 15 - -#define ADC_CHANNEL_COUNT 5 -#define AMUX_SELECT_PINS_COUNT 4 -#define AMUX_CHANNEL_COUNT 16 - -#define MATRIX_ROWS 5 -#define MATRIX_COLS 15 - -#define XXXX 0xff -#define ____ 0x00 - -#define SPECIAL(X) (0b1000000000000000 | X) /* USER CODE END Includes */ /* Exported types ------------------------------------------------------------*/ /* USER CODE BEGIN ET */ -struct __attribute__((__packed__)) calibration { - uint16_t cycles_count; - uint16_t idle_value; - uint16_t max_distance; -}; - -enum direction { - GOING_UP, - GOING_DOWN, -}; - -struct __attribute__((__packed__)) state { - uint16_t value; - uint16_t distance; - uint8_t distance_8bits; - float filtered_distance; - int8_t velocity; - uint8_t filtered_distance_8bits; -}; - -enum actuation_status { - STATUS_MIGHT_BE_TAP, - STATUS_TAP, - STATUS_TRIGGERED, - STATUS_RESET, - STATUS_RAPID_TRIGGER_RESET -}; - -struct __attribute__((__packed__)) actuation { - enum direction direction; - uint8_t direction_changed_point; - enum actuation_status status; - uint8_t reset_offset; - uint8_t trigger_offset; - uint8_t rapid_trigger_offset; - uint8_t is_continuous_rapid_trigger_enabled; - uint32_t triggered_at; -}; - -enum key_type { - KEY_TYPE_EMPTY, - KEY_TYPE_NORMAL, - KEY_TYPE_MODIFIER, - KEY_TYPE_CONSUMER_CONTROL, -}; - -struct __attribute__((__packed__)) layer { - enum key_type type; - uint16_t value; -}; - -enum { - _BASE_LAYER, - _TAP_LAYER, - LAYERS_COUNT -}; - -struct __attribute__((__packed__)) key { - uint8_t is_enabled; - uint8_t row; - uint8_t column; - uint8_t idle_counter; - uint8_t is_idle; - struct layer layers[LAYERS_COUNT]; - struct calibration calibration; - struct state state; - struct actuation actuation; -}; - -struct user_config { - uint8_t trigger_offset; - uint8_t reset_threshold; - uint8_t rapid_trigger_offset; - uint8_t screaming_velocity_trigger; - uint16_t tap_timeout; - uint16_t keymaps[LAYERS_COUNT][MATRIX_ROWS][MATRIX_COLS]; -}; + /* USER CODE END ET */ /* Exported constants --------------------------------------------------------*/ diff --git a/firmware/Core/Src/keyboard.c b/firmware/Core/Src/keyboard.c new file mode 100644 index 0000000..2f55648 --- /dev/null +++ b/firmware/Core/Src/keyboard.c @@ -0,0 +1,427 @@ +#include "keyboard.h" +#include "DRV2605L.h" +#include + +keyboard_user_config = {0}; + +const struct user_config default_user_config = { + .trigger_offset = DEFAULT_TRIGGER_OFFSET, + .reset_threshold = DEFAULT_RESET_THRESHOLD, + .rapid_trigger_offset = DEFAULT_RAPID_TRIGGER_OFFSET, + .screaming_velocity_trigger = DEFAULT_SCREAMING_VELOCITY_TRIGGER, + .tap_timeout = DEFAULT_TAP_TIMEOUT, + .keymaps = { + // clang-format off + [_BASE_LAYER] = { + {HID_KEY_ESCAPE, HID_KEY_GRAVE, HID_KEY_1, HID_KEY_2, HID_KEY_3, HID_KEY_4, HID_KEY_5, HID_KEY_6, HID_KEY_7, HID_KEY_8, HID_KEY_9, HID_KEY_0, HID_KEY_MINUS, HID_KEY_EQUAL, HID_KEY_BACKSPACE}, + {SPECIAL(HID_USAGE_CONSUMER_VOLUME_INCREMENT), HID_KEY_TAB, HID_KEY_Q, HID_KEY_W, HID_KEY_E, HID_KEY_R, HID_KEY_T, HID_KEY_Y, HID_KEY_U, HID_KEY_I, HID_KEY_O, HID_KEY_P, HID_KEY_BRACKET_LEFT, HID_KEY_BRACKET_RIGHT, HID_KEY_ENTER}, + {SPECIAL(HID_USAGE_CONSUMER_VOLUME_DECREMENT), HID_KEY_CAPS_LOCK, HID_KEY_A, HID_KEY_S, HID_KEY_D, HID_KEY_F, HID_KEY_G, HID_KEY_H, HID_KEY_J, HID_KEY_K, HID_KEY_L, HID_KEY_SEMICOLON, HID_KEY_APOSTROPHE, HID_KEY_EUROPE_1, XXXX}, + {XXXX, HID_KEY_SHIFT_LEFT, HID_KEY_EUROPE_2, HID_KEY_Z, HID_KEY_X, HID_KEY_C, HID_KEY_V, HID_KEY_B, HID_KEY_N, HID_KEY_M, HID_KEY_COMMA, HID_KEY_PERIOD, HID_KEY_SLASH, HID_KEY_SHIFT_RIGHT, XXXX}, + {XXXX, HID_KEY_CONTROL_LEFT, HID_KEY_ALT_LEFT, HID_KEY_GUI_LEFT, XXXX, HID_KEY_SPACE, XXXX, HID_KEY_SPACE, XXXX, HID_KEY_GUI_RIGHT, HID_KEY_ALT_RIGHT, XXXX, HID_KEY_ARROW_LEFT, SPECIAL(HID_USAGE_CONSUMER_PLAY_PAUSE), HID_KEY_ARROW_RIGHT}, + }, + [_TAP_LAYER] = { + {____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____}, + {____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____}, + {____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, XXXX}, + {XXXX, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, HID_KEY_ARROW_UP, XXXX}, + {XXXX, ____, ____, ____, XXXX, ____, XXXX, ____, XXXX, ____, ____, XXXX, ____, HID_KEY_ARROW_DOWN, ____}, + }, + // clang-format on + }}; + +// {adc_channel, amux_channel} +const uint8_t channels_by_row_col[MATRIX_ROWS][MATRIX_COLS][2] = { + {{0, 10}, {0, 8}, {0, 7}, {0, 5}, {1, 9}, {1, 8}, {1, 6}, {2, 10}, {2, 9}, {2, 7}, {2, 6}, {3, 9}, {3, 8}, {3, 6}, {4, 2}}, + {{0, 11}, {0, 9}, {0, 6}, {0, 4}, {1, 10}, {1, 7}, {1, 5}, {2, 11}, {2, 8}, {2, 5}, {2, 4}, {3, 10}, {3, 7}, {3, 5}, {4, 1}}, + {{0, 12}, {0, 14}, {0, 2}, {1, 11}, {1, 14}, {1, 1}, {1, 4}, {2, 12}, {2, 15}, {2, 3}, {3, 11}, {3, 14}, {3, 1}, {3, 4}, {XXXX, XXXX}}, + {{XXXX, XXXX}, {0, 13}, {0, 0}, {0, 3}, {1, 13}, {1, 15}, {1, 2}, {1, 3}, {2, 14}, {2, 0}, {2, 2}, {3, 12}, {3, 15}, {3, 3}, {XXXX, XXXX}}, + {{XXXX, XXXX}, {0, 15}, {0, 1}, {1, 12}, {XXXX, XXXX}, {1, 0}, {XXXX, XXXX}, {2, 13}, {XXXX, XXXX}, {2, 1}, {3, 13}, {XXXX, XXXX}, {3, 0}, {3, 2}, {4, 0}}, +}; + +static struct key keys[ADC_CHANNEL_COUNT][AMUX_CHANNEL_COUNT] = {0}; + +static uint8_t key_triggered = 0; + +static uint8_t should_send_consumer_report = 0; +static uint8_t should_send_keyboard_report = 0; + +static uint8_t modifiers = 0; +static uint8_t keycodes[6] = {0}; +static uint8_t is_screaming = 0; +static uint8_t consumer_report = 0; + +void keyboard_task() { + key_triggered = 0; + + for (uint8_t amux_channel = 0; amux_channel < AMUX_CHANNEL_COUNT; amux_channel++) { + keyboard_select_amux(amux_channel); + + for (uint8_t adc_channel = 0; adc_channel < ADC_CHANNEL_COUNT; adc_channel++) { + if (keys[adc_channel][amux_channel].is_enabled == 0) { + continue; + } + keyboard_select_adc(adc_channel); + + update_key(&keys[adc_channel][amux_channel]); + + keyboard_close_adc(); + } + } + + // If a key might be tap and a non tap key has been triggered, then the might be tap key is a normal trigger + for (uint8_t amux_channel = 0; amux_channel < AMUX_CHANNEL_COUNT; amux_channel++) { + for (uint8_t adc_channel = 0; adc_channel < ADC_CHANNEL_COUNT; adc_channel++) { + if (keys[adc_channel][amux_channel].is_enabled == 0 || keys[adc_channel][amux_channel].actuation.status != STATUS_MIGHT_BE_TAP) { + continue; + } + + struct key *key = &keys[adc_channel][amux_channel]; + uint8_t is_before_reset_offset = key->state.distance_8bits < key->actuation.reset_offset; + uint8_t is_before_timeout = keyboard_get_time() - key->actuation.triggered_at <= keyboard_user_config.tap_timeout; + + // if might be tap, can be tap or triggered + if (is_before_reset_offset && is_before_timeout) { + key->actuation.status = STATUS_TAP; + add_to_hid_report(key, _TAP_LAYER); + } else if (!is_before_timeout || key_triggered) { + key->actuation.status = STATUS_TRIGGERED; + add_to_hid_report(key, _BASE_LAYER); + } + } + } + + /** + * @todo + * @todo + * @todo + * @todo + * split keycode and stuff in another file + */ + if ((should_send_consumer_report || should_send_keyboard_report) && tud_hid_ready()) { + if (tud_suspended()) { + tud_remote_wakeup(); + } else { + if (should_send_consumer_report) { + should_send_consumer_report = 0; + tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &consumer_report, 2); + } else if (should_send_keyboard_report) { + should_send_keyboard_report = 0; + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, modifiers, keycodes); + } + } + } +} + +uint8_t get_bitmask_for_modifier(uint8_t keycode) { + switch (keycode) { + case HID_KEY_CONTROL_LEFT: + return 0b00000001; + case HID_KEY_SHIFT_LEFT: + return 0b00000010; + case HID_KEY_ALT_LEFT: + return 0b00000100; + case HID_KEY_GUI_LEFT: + return 0b00001000; + case HID_KEY_CONTROL_RIGHT: + return 0b00010000; + case HID_KEY_SHIFT_RIGHT: + return 0b00100000; + case HID_KEY_ALT_RIGHT: + return 0b01000000; + case HID_KEY_GUI_RIGHT: + return 0b10000000; + default: + return 0b00000000; + } +} + +uint16_t get_usage_consumer_control(uint16_t value) { + if (value > 0xFF) { + return value & 0b0111111111111111; + } else { + return 0; + } +} + +void init_key(uint8_t adc_channel, uint8_t amux_channel, uint8_t row, uint8_t column) { + struct key *key = &keys[adc_channel][amux_channel]; + + key->is_enabled = 1; + key->is_idle = 0; + key->row = row; + key->column = column; + + key->calibration.cycles_count = 0; + key->calibration.idle_value = IDLE_VALUE_APPROX; + key->calibration.max_distance = MAX_DISTANCE_APPROX; + + key->actuation.status = STATUS_RESET; + key->actuation.trigger_offset = keyboard_user_config.trigger_offset; + key->actuation.reset_offset = keyboard_user_config.trigger_offset - keyboard_user_config.reset_threshold; + key->actuation.rapid_trigger_offset = keyboard_user_config.rapid_trigger_offset; + key->actuation.is_continuous_rapid_trigger_enabled = 0; + + for (uint8_t i = 0; i < LAYERS_COUNT; i++) { + if (keyboard_user_config.keymaps[i][row][column] != ____) { + uint16_t usage_consumer_control = get_usage_consumer_control(keyboard_user_config.keymaps[i][row][column]); + if (usage_consumer_control) { + key->layers[i].type = KEY_TYPE_CONSUMER_CONTROL; + key->layers[i].value = usage_consumer_control; + } else { + uint8_t bitmask = get_bitmask_for_modifier(keyboard_user_config.keymaps[i][row][column]); + if (bitmask) { + key->layers[i].type = KEY_TYPE_MODIFIER; + key->layers[i].value = bitmask; + } else { + key->layers[i].type = KEY_TYPE_NORMAL; + key->layers[i].value = keyboard_user_config.keymaps[i][row][column]; + } + } + } + } +} + +void keyboard_init_keys() { + keyboard_read_config(); + + for (uint8_t row = 0; row < MATRIX_ROWS; row++) { + for (uint8_t col = 0; col < MATRIX_COLS; col++) { + if (channels_by_row_col[row][col][0] != XXXX) { + init_key(channels_by_row_col[row][col][0], channels_by_row_col[row][col][1], row, col); + } + } + } +} + +void add_to_hid_report(struct key *key, uint8_t layer) { + switch (key->layers[layer].type) { + case KEY_TYPE_MODIFIER: + modifiers |= key->layers[layer].value; + should_send_keyboard_report = 1; + break; + + case KEY_TYPE_NORMAL: + for (uint8_t i = 0; i < 6; i++) { + if (keycodes[i] == 0) { + keycodes[i] = key->layers[layer].value; + // if the key is violently pressed, automatically add the MAJ modifier :) + // if (is_screaming) { + // is_screaming = 0; + // modifiers &= ~get_bitmask_for_modifier(HID_KEY_SHIFT_LEFT); + // } else if (i == 0 && key->state.velocity > keyboard_user_config.screaming_velocity_trigger) { + // is_screaming = 1; + // modifiers |= get_bitmask_for_modifier(HID_KEY_SHIFT_LEFT); + // } + should_send_keyboard_report = 1; + break; + } + } + break; + + case KEY_TYPE_CONSUMER_CONTROL: + consumer_report = key->layers[layer].value; + should_send_consumer_report = 1; + break; + } +} + +void remove_from_hid_report(struct key *key, uint8_t layer) { + switch (key->layers[layer].type) { + case KEY_TYPE_MODIFIER: + modifiers &= ~key->layers[layer].value; + should_send_keyboard_report = 1; + break; + + case KEY_TYPE_NORMAL: + for (uint8_t i = 0; i < 6; i++) { + if (keycodes[i] == key->layers[layer].value) { + keycodes[i] = 0; + // if (is_screaming) { + // is_screaming = 0; + // modifiers &= ~get_bitmask_for_modifier(HID_KEY_SHIFT_LEFT); + // } + should_send_keyboard_report = 1; + break; + } + } + break; + + case KEY_TYPE_CONSUMER_CONTROL: + consumer_report = 0; + should_send_consumer_report = 1; + break; + } +} + +uint8_t update_key_state(struct key *key) { + struct state state; + + // Get a reading + state.value = keyboard_read_adc(); + + if (key->calibration.cycles_count < CALIBRATION_CYCLES) { + // Calibrate idle value + float delta = 0.6; + key->calibration.idle_value = (1 - delta) * state.value + delta * key->calibration.idle_value; + key->calibration.cycles_count++; + + return 0; + } + + // Calibrate idle value + if (state.value > key->calibration.idle_value) { + // opti possible sur float + float delta = 0.8; + key->calibration.idle_value = (1 - delta) * state.value + delta * key->calibration.idle_value; + state.value = key->calibration.idle_value; + } + + // Do nothing if key is idle + if (key->state.distance == 0 && state.value >= key->calibration.idle_value - IDLE_VALUE_OFFSET) { + if (key->idle_counter >= IDLE_CYCLES_UNTIL_SLEEP) { + key->is_idle = 1; + return 0; + } + key->idle_counter++; + } + + // Get distance from top + if (state.value >= key->calibration.idle_value - IDLE_VALUE_OFFSET) { + state.distance = 0; + key->actuation.direction_changed_point = 0; + } else { + state.distance = key->calibration.idle_value - IDLE_VALUE_OFFSET - state.value; + key->is_idle = 0; + key->idle_counter = 0; + } + + // Calibrate max distance value + if (state.distance > key->calibration.max_distance) { + key->calibration.max_distance = state.distance; + } + + // Limit max distance + if (state.distance >= key->calibration.max_distance - MAX_DISTANCE_OFFSET) { + state.distance = key->calibration.max_distance; + } + + // Map distance in percentages + state.distance_8bits = (state.distance * 0xff) / key->calibration.max_distance; + + float delta = 0.8; + state.filtered_distance = (1 - delta) * state.distance_8bits + delta * key->state.filtered_distance; + state.filtered_distance_8bits = state.filtered_distance; + + // Update velocity + state.velocity = state.filtered_distance_8bits - key->state.filtered_distance_8bits; + + // Update direction + if (key->state.velocity > 0 && state.velocity > 0 && key->actuation.direction != GOING_DOWN) { + key->actuation.direction = GOING_DOWN; + if (key->actuation.direction_changed_point != 0) { + key->actuation.direction_changed_point = key->state.filtered_distance_8bits; + } + } else if (key->state.velocity < 0 && state.velocity < 0 && key->actuation.direction != GOING_UP) { + key->actuation.direction = GOING_UP; + if (key->actuation.direction_changed_point != 255) { + key->actuation.direction_changed_point = key->state.filtered_distance_8bits; + } + } + + key->state = state; + return 1; +} + +void update_key_actuation(struct key *key) { + /** + * https://www.youtube.com/watch?v=_Sl-T6iQr8U&t + * + * ----- |--------| - + * | | | | + * is_before_reset_offset | | | | + * | | | | Continuous rapid trigger domain (deactivated when full_reset) + * ----- | ------ | <- reset_offset | + * | | | | + * ----- | ------ | <- trigger_offset - + * | | | | + * | | | | + * is_after_trigger_offset | | | | Rapid trigger domain + * | | | | + * | | | | + * ----- |--------| - + * + */ + + // if rapid trigger enable, move trigger and reset offsets according to the distance taht began the trigger + + uint32_t now = keyboard_get_time(); + uint8_t is_after_trigger_offset = key->state.distance_8bits > key->actuation.trigger_offset; + uint8_t is_before_reset_offset = key->state.distance_8bits < key->actuation.reset_offset; + uint8_t has_rapid_trigger = key->actuation.rapid_trigger_offset != 0; + uint8_t is_after_rapid_trigger_offset = key->state.distance_8bits > key->actuation.direction_changed_point - key->actuation.rapid_trigger_offset + keyboard_user_config.reset_threshold; + uint8_t is_before_rapid_reset_offset = key->state.distance_8bits < key->actuation.direction_changed_point - key->actuation.rapid_trigger_offset; + + switch (key->actuation.status) { + + case STATUS_RESET: + // if reset, can be triggered or tap + if (is_after_trigger_offset) { + if (key->layers[_TAP_LAYER].value) { + key->actuation.status = STATUS_MIGHT_BE_TAP; + // key_triggered = 1; + } else { + key->actuation.status = STATUS_TRIGGERED; + key_triggered = 1; + add_to_hid_report(key, _BASE_LAYER); + } + key->actuation.triggered_at = now; + } + break; + + case STATUS_RAPID_TRIGGER_RESET: + if (!has_rapid_trigger) { + key->actuation.status = STATUS_RESET; + break; + } + // if reset, can be triggered or tap + if (is_after_trigger_offset && key->actuation.direction == GOING_DOWN && is_after_rapid_trigger_offset) { + if (key->layers[_TAP_LAYER].value) { + key->actuation.status = STATUS_MIGHT_BE_TAP; + key_triggered = 1; + } else { + key->actuation.status = STATUS_TRIGGERED; + key_triggered = 1; + add_to_hid_report(key, _BASE_LAYER); + } + key->actuation.triggered_at = now; + } else if (is_before_reset_offset) { + key->actuation.status = STATUS_RESET; + } + break; + + case STATUS_TAP: + // if tap, can be reset + key->actuation.status = STATUS_RESET; + remove_from_hid_report(key, _TAP_LAYER); + break; + + case STATUS_TRIGGERED: + // if triggered, can be reset + if (is_before_reset_offset) { + key->actuation.status = STATUS_RESET; + remove_from_hid_report(key, _BASE_LAYER); + } else if (has_rapid_trigger && key->actuation.direction == GOING_UP && is_before_rapid_reset_offset) { + key->actuation.status = STATUS_RAPID_TRIGGER_RESET; + remove_from_hid_report(key, _BASE_LAYER); + } + break; + } +} + +void update_key(struct key *key) { + if (!update_key_state(key)) { + return; + } + + update_key_actuation(key); +} diff --git a/firmware/Core/Src/main.c b/firmware/Core/Src/main.c index e6e4d1a..53f8c5b 100644 --- a/firmware/Core/Src/main.c +++ b/firmware/Core/Src/main.c @@ -23,6 +23,7 @@ /* USER CODE BEGIN Includes */ #include "DRV2605L.h" #include "tusb.h" +#include "keyboard.h" #include "usb_descriptors.h" #include @@ -66,56 +67,9 @@ ADC_ChannelConfTypeDef ADC_channel_Config = {0}; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t usb_vendor_control_buffer[CFG_TUD_VENDOR_RX_BUFSIZE]; -struct user_config user_config = {0}; - -const struct user_config default_user_config = { - .trigger_offset = DEFAULT_TRIGGER_OFFSET, - .reset_threshold = DEFAULT_RESET_THRESHOLD, - .rapid_trigger_offset = DEFAULT_RAPID_TRIGGER_OFFSET, - .screaming_velocity_trigger = DEFAULT_SCREAMING_VELOCITY_TRIGGER, - .tap_timeout = DEFAULT_TAP_TIMEOUT, - .keymaps = { - // clang-format off - [_BASE_LAYER] = { - {HID_KEY_ESCAPE, HID_KEY_GRAVE, HID_KEY_1, HID_KEY_2, HID_KEY_3, HID_KEY_4, HID_KEY_5, HID_KEY_6, HID_KEY_7, HID_KEY_8, HID_KEY_9, HID_KEY_0, HID_KEY_MINUS, HID_KEY_EQUAL, HID_KEY_BACKSPACE}, - {SPECIAL(HID_USAGE_CONSUMER_VOLUME_INCREMENT), HID_KEY_TAB, HID_KEY_Q, HID_KEY_W, HID_KEY_E, HID_KEY_R, HID_KEY_T, HID_KEY_Y, HID_KEY_U, HID_KEY_I, HID_KEY_O, HID_KEY_P, HID_KEY_BRACKET_LEFT, HID_KEY_BRACKET_RIGHT, HID_KEY_ENTER}, - {SPECIAL(HID_USAGE_CONSUMER_VOLUME_DECREMENT), HID_KEY_CAPS_LOCK, HID_KEY_A, HID_KEY_S, HID_KEY_D, HID_KEY_F, HID_KEY_G, HID_KEY_H, HID_KEY_J, HID_KEY_K, HID_KEY_L, HID_KEY_SEMICOLON, HID_KEY_APOSTROPHE, HID_KEY_EUROPE_1, XXXX}, - {XXXX, HID_KEY_SHIFT_LEFT, HID_KEY_EUROPE_2, HID_KEY_Z, HID_KEY_X, HID_KEY_C, HID_KEY_V, HID_KEY_B, HID_KEY_N, HID_KEY_M, HID_KEY_COMMA, HID_KEY_PERIOD, HID_KEY_SLASH, HID_KEY_SHIFT_RIGHT, XXXX}, - {XXXX, HID_KEY_CONTROL_LEFT, HID_KEY_ALT_LEFT, HID_KEY_GUI_LEFT, XXXX, HID_KEY_SPACE, XXXX, HID_KEY_SPACE, XXXX, HID_KEY_GUI_RIGHT, HID_KEY_ALT_RIGHT, XXXX, HID_KEY_ARROW_LEFT, SPECIAL(HID_USAGE_CONSUMER_PLAY_PAUSE), HID_KEY_ARROW_RIGHT}, - }, - [_TAP_LAYER] = { - {____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____}, - {____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____}, - {____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, XXXX}, - {XXXX, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, HID_KEY_ARROW_UP, XXXX}, - {XXXX, ____, ____, ____, XXXX, ____, XXXX, ____, XXXX, ____, ____, XXXX, ____, HID_KEY_ARROW_DOWN, ____}, - }, - // clang-format on - }}; - -// {adc_channel, amux_channel} -const uint8_t channels_by_row_col[MATRIX_ROWS][MATRIX_COLS][2] = { - {{0, 10}, {0, 8}, {0, 7}, {0, 5}, {1, 9}, {1, 8}, {1, 6}, {2, 10}, {2, 9}, {2, 7}, {2, 6}, {3, 9}, {3, 8}, {3, 6}, {4, 2}}, - {{0, 11}, {0, 9}, {0, 6}, {0, 4}, {1, 10}, {1, 7}, {1, 5}, {2, 11}, {2, 8}, {2, 5}, {2, 4}, {3, 10}, {3, 7}, {3, 5}, {4, 1}}, - {{0, 12}, {0, 14}, {0, 2}, {1, 11}, {1, 14}, {1, 1}, {1, 4}, {2, 12}, {2, 15}, {2, 3}, {3, 11}, {3, 14}, {3, 1}, {3, 4}, {XXXX, XXXX}}, - {{XXXX, XXXX}, {0, 13}, {0, 0}, {0, 3}, {1, 13}, {1, 15}, {1, 2}, {1, 3}, {2, 14}, {2, 0}, {2, 2}, {3, 12}, {3, 15}, {3, 3}, {XXXX, XXXX}}, - {{XXXX, XXXX}, {0, 15}, {0, 1}, {1, 12}, {XXXX, XXXX}, {1, 0}, {XXXX, XXXX}, {2, 13}, {XXXX, XXXX}, {2, 1}, {3, 13}, {XXXX, XXXX}, {3, 0}, {3, 2}, {4, 0}}, -}; - const uint32_t adc_channels[ADC_CHANNEL_COUNT] = {ADC_CHANNEL_3, ADC_CHANNEL_4, ADC_CHANNEL_5, ADC_CHANNEL_6, ADC_CHANNEL_7}; -const uint32_t amux_select_pins[AMUX_SELECT_PINS_COUNT] = {GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_14, GPIO_PIN_15}; - -static struct key keys[ADC_CHANNEL_COUNT][AMUX_CHANNEL_COUNT] = {0}; - -static uint8_t key_triggered = 0; -static uint8_t should_send_consumer_report = 0; -static uint8_t should_send_keyboard_report = 0; - -static uint8_t modifiers = 0; -static uint8_t keycodes[6] = {0}; -static uint8_t is_screaming = 0; -static uint8_t consumer_report = 0; +const uint32_t amux_select_pins[AMUX_SELECT_PINS_COUNT] = {GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_14, GPIO_PIN_15}; extern uint8_t const desc_ms_os_20[]; @@ -130,10 +84,6 @@ static void MX_USB_OTG_FS_PCD_Init(void); static void MX_I2C1_Init(void); #endif /* USER CODE BEGIN PFP */ -static void update_key(struct key *key); -static void init_keys(); -static void add_to_hid_report(struct key *key, uint8_t layer); -static void remove_from_hid_report(struct key *key, uint8_t layer); /* USER CODE END PFP */ @@ -159,27 +109,6 @@ void jump_to_bootloader(void) { } } -void readConfig() { - memcpy(&user_config, (uint32_t *)CONFIG_ADDRESS, sizeof(user_config)); -} - -bool writeConfig(uint8_t *buffer, uint16_t offset, uint16_t size) { - if (offset >= sizeof user_config) { - return false; - } - - HAL_FLASH_Unlock(); - __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR); - FLASH_Erase_Sector(FLASH_SECTOR_6, VOLTAGE_RANGE_3); - for (uint16_t i = offset; i < size; i++) { - if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, CONFIG_ADDRESS + i, buffer[i]) != HAL_OK) { - HAL_FLASH_Lock(); - }; - } - HAL_FLASH_Lock(); - return true; -} - uint8_t readRegister8(uint8_t reg) { uint8_t buffer[1] = {reg}; HAL_I2C_Master_Transmit(&hi2c1, DRV2605_ADDR << 1, buffer, 1, 1000); @@ -260,7 +189,9 @@ int main(void) { #endif /* USER CODE BEGIN 2 */ - init_keys(); + ADC_channel_Config.Rank = 1; + ADC_channel_Config.SamplingTime = ADC_SAMPLETIME_3CYCLES; + keyboard_init_keys(); tud_init(BOARD_TUD_RHPORT); #if IS_DRV2605_ENABLED @@ -275,65 +206,7 @@ int main(void) { // MARK: Main loop tud_task(); - key_triggered = 0; - - for (uint8_t amux_channel = 0; amux_channel < AMUX_CHANNEL_COUNT; amux_channel++) { - // TODO: set GPIOs at the same time using bitmap on register - for (uint8_t i = 0; i < AMUX_SELECT_PINS_COUNT; i++) { - HAL_GPIO_WritePin(GPIOB, amux_select_pins[i], (amux_channel >> i) & 1); - } - - for (uint8_t adc_channel = 0; adc_channel < ADC_CHANNEL_COUNT; adc_channel++) { - if (keys[adc_channel][amux_channel].is_enabled == 0) { - continue; - } - - ADC_channel_Config.Channel = adc_channels[adc_channel]; - HAL_ADC_ConfigChannel(&hadc1, &ADC_channel_Config); - HAL_ADC_Start(&hadc1); - HAL_ADC_PollForConversion(&hadc1, 1); - - update_key(&keys[adc_channel][amux_channel]); - - HAL_ADC_Stop(&hadc1); - } - } - - // If a key might be tap and a non tap key has been triggered, then the might be tap key is a normal trigger - for (uint8_t amux_channel = 0; amux_channel < AMUX_CHANNEL_COUNT; amux_channel++) { - for (uint8_t adc_channel = 0; adc_channel < ADC_CHANNEL_COUNT; adc_channel++) { - if (keys[adc_channel][amux_channel].is_enabled == 0 || keys[adc_channel][amux_channel].actuation.status != STATUS_MIGHT_BE_TAP) { - continue; - } - - struct key *key = &keys[adc_channel][amux_channel]; - uint8_t is_before_reset_offset = key->state.distance_8bits < key->actuation.reset_offset; - uint8_t is_before_timeout = HAL_GetTick() - key->actuation.triggered_at <= user_config.tap_timeout; - - // if might be tap, can be tap or triggered - if (is_before_reset_offset && is_before_timeout) { - key->actuation.status = STATUS_TAP; - add_to_hid_report(key, _TAP_LAYER); - } else if (!is_before_timeout || key_triggered) { - key->actuation.status = STATUS_TRIGGERED; - add_to_hid_report(key, _BASE_LAYER); - } - } - } - - if ((should_send_consumer_report || should_send_keyboard_report) && tud_hid_ready()) { - if (tud_suspended()) { - tud_remote_wakeup(); - } else { - if (should_send_consumer_report) { - should_send_consumer_report = 0; - tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &consumer_report, 2); - } else if (should_send_keyboard_report) { - should_send_keyboard_report = 0; - tud_hid_keyboard_report(REPORT_ID_KEYBOARD, modifiers, keycodes); - } - } - } + keyboard_task(); #if IS_DRV2605_ENABLED if (key_triggered) { @@ -533,321 +406,54 @@ static void MX_GPIO_Init(void) { } /* USER CODE BEGIN 4 */ -uint8_t get_bitmask_for_modifier(uint8_t keycode) { - switch (keycode) { - case HID_KEY_CONTROL_LEFT: - return 0b00000001; - case HID_KEY_SHIFT_LEFT: - return 0b00000010; - case HID_KEY_ALT_LEFT: - return 0b00000100; - case HID_KEY_GUI_LEFT: - return 0b00001000; - case HID_KEY_CONTROL_RIGHT: - return 0b00010000; - case HID_KEY_SHIFT_RIGHT: - return 0b00100000; - case HID_KEY_ALT_RIGHT: - return 0b01000000; - case HID_KEY_GUI_RIGHT: - return 0b10000000; - default: - return 0b00000000; - } -} -uint16_t get_usage_consumer_control(uint16_t value) { - if (value > 0xFF) { - return value & 0b0111111111111111; - } else { - return 0; - } -} +// MARK: keyboard_* functions -void init_key(uint8_t adc_channel, uint8_t amux_channel, uint8_t row, uint8_t column) { - struct key *key = &keys[adc_channel][amux_channel]; - - key->is_enabled = 1; - key->is_idle = 0; - key->row = row; - key->column = column; - - key->calibration.cycles_count = 0; - key->calibration.idle_value = IDLE_VALUE_APPROX; - key->calibration.max_distance = MAX_DISTANCE_APPROX; - - key->actuation.status = STATUS_RESET; - key->actuation.trigger_offset = user_config.trigger_offset; - key->actuation.reset_offset = user_config.trigger_offset - user_config.reset_threshold; - key->actuation.rapid_trigger_offset = user_config.rapid_trigger_offset; - key->actuation.is_continuous_rapid_trigger_enabled = 0; - - for (uint8_t i = 0; i < LAYERS_COUNT; i++) { - if (user_config.keymaps[i][row][column] != ____) { - uint16_t usage_consumer_control = get_usage_consumer_control(user_config.keymaps[i][row][column]); - if (usage_consumer_control) { - key->layers[i].type = KEY_TYPE_CONSUMER_CONTROL; - key->layers[i].value = usage_consumer_control; - } else { - uint8_t bitmask = get_bitmask_for_modifier(user_config.keymaps[i][row][column]); - if (bitmask) { - key->layers[i].type = KEY_TYPE_MODIFIER; - key->layers[i].value = bitmask; - } else { - key->layers[i].type = KEY_TYPE_NORMAL; - key->layers[i].value = user_config.keymaps[i][row][column]; - } - } - } - } +void keyboard_read_config() { + memcpy(&keyboard_user_config, (uint32_t *)CONFIG_ADDRESS, sizeof(keyboard_user_config)); } -void init_keys() { - readConfig(); - - ADC_channel_Config.Rank = 1; - ADC_channel_Config.SamplingTime = ADC_SAMPLETIME_3CYCLES; - - for (uint8_t row = 0; row < MATRIX_ROWS; row++) { - for (uint8_t col = 0; col < MATRIX_COLS; col++) { - if (channels_by_row_col[row][col][0] != XXXX) { - init_key(channels_by_row_col[row][col][0], channels_by_row_col[row][col][1], row, col); - } - } +uint8_t keyboard_write_config(uint8_t *buffer, uint16_t offset, uint16_t size) { + if (offset >= sizeof keyboard_user_config) { + return false; } -} - -void add_to_hid_report(struct key *key, uint8_t layer) { - switch (key->layers[layer].type) { - case KEY_TYPE_MODIFIER: - modifiers |= key->layers[layer].value; - should_send_keyboard_report = 1; - break; - - case KEY_TYPE_NORMAL: - for (uint8_t i = 0; i < 6; i++) { - if (keycodes[i] == 0) { - keycodes[i] = key->layers[layer].value; - // if the key is violently pressed, automatically add the MAJ modifier :) - // if (is_screaming) { - // is_screaming = 0; - // modifiers &= ~get_bitmask_for_modifier(HID_KEY_SHIFT_LEFT); - // } else if (i == 0 && key->state.velocity > user_config.screaming_velocity_trigger) { - // is_screaming = 1; - // modifiers |= get_bitmask_for_modifier(HID_KEY_SHIFT_LEFT); - // } - should_send_keyboard_report = 1; - break; - } - } - break; - case KEY_TYPE_CONSUMER_CONTROL: - consumer_report = key->layers[layer].value; - should_send_consumer_report = 1; - break; + HAL_FLASH_Unlock(); + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR); + FLASH_Erase_Sector(FLASH_SECTOR_6, VOLTAGE_RANGE_3); + for (uint16_t i = offset; i < size; i++) { + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, CONFIG_ADDRESS + i, buffer[i]) != HAL_OK) { + HAL_FLASH_Lock(); + }; } + HAL_FLASH_Lock(); + return true; } -void remove_from_hid_report(struct key *key, uint8_t layer) { - switch (key->layers[layer].type) { - case KEY_TYPE_MODIFIER: - modifiers &= ~key->layers[layer].value; - should_send_keyboard_report = 1; - break; - - case KEY_TYPE_NORMAL: - for (uint8_t i = 0; i < 6; i++) { - if (keycodes[i] == key->layers[layer].value) { - keycodes[i] = 0; - // if (is_screaming) { - // is_screaming = 0; - // modifiers &= ~get_bitmask_for_modifier(HID_KEY_SHIFT_LEFT); - // } - should_send_keyboard_report = 1; - break; - } - } - break; - - case KEY_TYPE_CONSUMER_CONTROL: - consumer_report = 0; - should_send_consumer_report = 1; - break; +void keyboard_select_amux(uint8_t amux_channel) { + // TODO: set GPIOs at the same time using bitmap on register + for (uint8_t i = 0; i < AMUX_SELECT_PINS_COUNT; i++) { + HAL_GPIO_WritePin(GPIOB, amux_select_pins[i], (amux_channel >> i) & 1); } } -uint8_t update_key_state(struct key *key) { - struct state state; - - // Get a reading - state.value = HAL_ADC_GetValue(&hadc1); - - if (key->calibration.cycles_count < CALIBRATION_CYCLES) { - // Calibrate idle value - float delta = 0.6; - key->calibration.idle_value = (1 - delta) * state.value + delta * key->calibration.idle_value; - key->calibration.cycles_count++; - - return 0; - } - - // Calibrate idle value - if (state.value > key->calibration.idle_value) { - // opti possible sur float - float delta = 0.8; - key->calibration.idle_value = (1 - delta) * state.value + delta * key->calibration.idle_value; - state.value = key->calibration.idle_value; - } - - // Do nothing if key is idle - if (key->state.distance == 0 && state.value >= key->calibration.idle_value - IDLE_VALUE_OFFSET) { - if (key->idle_counter >= IDLE_CYCLES_UNTIL_SLEEP) { - key->is_idle = 1; - return 0; - } - key->idle_counter++; - } - - // Get distance from top - if (state.value >= key->calibration.idle_value - IDLE_VALUE_OFFSET) { - state.distance = 0; - key->actuation.direction_changed_point = 0; - } else { - state.distance = key->calibration.idle_value - IDLE_VALUE_OFFSET - state.value; - key->is_idle = 0; - key->idle_counter = 0; - } - - // Calibrate max distance value - if (state.distance > key->calibration.max_distance) { - key->calibration.max_distance = state.distance; - } - - // Limit max distance - if (state.distance >= key->calibration.max_distance - MAX_DISTANCE_OFFSET) { - state.distance = key->calibration.max_distance; - } - - // Map distance in percentages - state.distance_8bits = (state.distance * 0xff) / key->calibration.max_distance; - - float delta = 0.8; - state.filtered_distance = (1 - delta) * state.distance_8bits + delta * key->state.filtered_distance; - state.filtered_distance_8bits = state.filtered_distance; - - // Update velocity - state.velocity = state.filtered_distance_8bits - key->state.filtered_distance_8bits; - - // Update direction - if (key->state.velocity > 0 && state.velocity > 0 && key->actuation.direction != GOING_DOWN) { - key->actuation.direction = GOING_DOWN; - if (key->actuation.direction_changed_point != 0) { - key->actuation.direction_changed_point = key->state.filtered_distance_8bits; - } - } else if (key->state.velocity < 0 && state.velocity < 0 && key->actuation.direction != GOING_UP) { - key->actuation.direction = GOING_UP; - if (key->actuation.direction_changed_point != 255) { - key->actuation.direction_changed_point = key->state.filtered_distance_8bits; - } - } - - key->state = state; - return 1; +void keyboard_select_adc(uint8_t adc_channel) { + ADC_channel_Config.Channel = adc_channels[adc_channel]; + HAL_ADC_ConfigChannel(&hadc1, &ADC_channel_Config); + HAL_ADC_Start(&hadc1); + HAL_ADC_PollForConversion(&hadc1, 1); } -void update_key_actuation(struct key *key) { - /** - * https://www.youtube.com/watch?v=_Sl-T6iQr8U&t - * - * ----- |--------| - - * | | | | - * is_before_reset_offset | | | | - * | | | | Continuous rapid trigger domain (deactivated when full_reset) - * ----- | ------ | <- reset_offset | - * | | | | - * ----- | ------ | <- trigger_offset - - * | | | | - * | | | | - * is_after_trigger_offset | | | | Rapid trigger domain - * | | | | - * | | | | - * ----- |--------| - - * - */ - - // if rapid trigger enable, move trigger and reset offsets according to the distance taht began the trigger - - uint32_t now = HAL_GetTick(); - uint8_t is_after_trigger_offset = key->state.distance_8bits > key->actuation.trigger_offset; - uint8_t is_before_reset_offset = key->state.distance_8bits < key->actuation.reset_offset; - uint8_t has_rapid_trigger = key->actuation.rapid_trigger_offset != 0; - uint8_t is_after_rapid_trigger_offset = key->state.distance_8bits > key->actuation.direction_changed_point - key->actuation.rapid_trigger_offset + user_config.reset_threshold; - uint8_t is_before_rapid_reset_offset = key->state.distance_8bits < key->actuation.direction_changed_point - key->actuation.rapid_trigger_offset; - - switch (key->actuation.status) { - - case STATUS_RESET: - // if reset, can be triggered or tap - if (is_after_trigger_offset) { - if (key->layers[_TAP_LAYER].value) { - key->actuation.status = STATUS_MIGHT_BE_TAP; - // key_triggered = 1; - } else { - key->actuation.status = STATUS_TRIGGERED; - key_triggered = 1; - add_to_hid_report(key, _BASE_LAYER); - } - key->actuation.triggered_at = now; - } - break; - - case STATUS_RAPID_TRIGGER_RESET: - if (!has_rapid_trigger) { - key->actuation.status = STATUS_RESET; - break; - } - // if reset, can be triggered or tap - if (is_after_trigger_offset && key->actuation.direction == GOING_DOWN && is_after_rapid_trigger_offset) { - if (key->layers[_TAP_LAYER].value) { - key->actuation.status = STATUS_MIGHT_BE_TAP; - key_triggered = 1; - } else { - key->actuation.status = STATUS_TRIGGERED; - key_triggered = 1; - add_to_hid_report(key, _BASE_LAYER); - } - key->actuation.triggered_at = now; - } else if (is_before_reset_offset) { - key->actuation.status = STATUS_RESET; - } - break; - - case STATUS_TAP: - // if tap, can be reset - key->actuation.status = STATUS_RESET; - remove_from_hid_report(key, _TAP_LAYER); - break; - - case STATUS_TRIGGERED: - // if triggered, can be reset - if (is_before_reset_offset) { - key->actuation.status = STATUS_RESET; - remove_from_hid_report(key, _BASE_LAYER); - } else if (has_rapid_trigger && key->actuation.direction == GOING_UP && is_before_rapid_reset_offset) { - key->actuation.status = STATUS_RAPID_TRIGGER_RESET; - remove_from_hid_report(key, _BASE_LAYER); - } - break; - } +uint16_t keyboard_read_adc() { + return HAL_ADC_GetValue(&hadc1); } -void update_key(struct key *key) { - if (!update_key_state(key)) { - return; - } +void keyboard_close_adc() { + HAL_ADC_Stop(&hadc1); +} - update_key_actuation(key); +uint32_t keyboard_get_time() { + return HAL_GetTick(); } // MARK: tud_* functions @@ -903,7 +509,7 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_ // // connected // if (dtr && rts) { // // print initial message when connected -// tud_cdc_write(&user_config, 3); +// tud_cdc_write(&keyboard_user_config, 3); // tud_cdc_write_str('\r\n'); // tud_cdc_write_flush(); // } @@ -926,7 +532,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ switch (request->wValue) { case VENDOR_VALUE_GET_LENGTH: { if (stage == CONTROL_STAGE_SETUP) { - uint16_t size = sizeof(user_config); + uint16_t size = sizeof(keyboard_user_config); return tud_control_xfer(rhport, request, &size, request->wLength); } @@ -935,7 +541,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ case VENDOR_VALUE_GET: { if (stage == CONTROL_STAGE_SETUP) { - return tud_control_xfer(rhport, request, &user_config, request->wLength); + return tud_control_xfer(rhport, request, &keyboard_user_config, request->wLength); } break; @@ -963,7 +569,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ case VENDOR_REQUEST_RESET_CONFIG: { if (request->wValue == VENDOR_VALUE_SET) { if (stage == CONTROL_STAGE_SETUP) { - if (!writeConfig(&default_user_config, 0, sizeof default_user_config)) { + if (!writeConfig(&default_keyboard_user_config, 0, sizeof default_keyboard_user_config)) { return false; } readConfig();