drashna.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "drashna.h"
  4. userspace_config_t userspace_config;
  5. /**
  6. * @brief Handle registering a keycode, with optional modifer based on timed event
  7. *
  8. * @param code keycode to send to host
  9. * @param mod_code modifier to send with code, if held for tapping term or longer
  10. * @param pressed the press/release event (can use "record->event.pressed" for this)
  11. * @return true exits function
  12. * @return false exits function
  13. */
  14. bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed) {
  15. static uint16_t this_timer;
  16. mod_key_press(code, mod_code, pressed, this_timer);
  17. return false;
  18. }
  19. /**
  20. * @brief Handle registation of keycode, with optional modifier based on custom timer
  21. *
  22. * @param code keycode to send to host
  23. * @param mod_code modifier keycode to send with code, if held for tapping term or longer
  24. * @param pressed the press/release event
  25. * @param this_timer custom timer to use
  26. * @return true
  27. * @return false
  28. */
  29. bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer) {
  30. if (pressed) {
  31. this_timer = timer_read();
  32. } else {
  33. if (timer_elapsed(this_timer) < TAPPING_TERM) {
  34. tap_code(code);
  35. } else {
  36. register_code(mod_code);
  37. tap_code(code);
  38. unregister_code(mod_code);
  39. }
  40. }
  41. return false;
  42. }
  43. /**
  44. * @brief Performs exact match for modifier values
  45. *
  46. * @param value the modifer varible (get_mods/get_oneshot_mods/get_weak_mods)
  47. * @param mask the modifier mask to check for
  48. * @return true Has the exact modifiers specifed
  49. * @return false Does not have the exact modifiers specified
  50. */
  51. bool hasAllBitsInMask(uint8_t value, uint8_t mask) {
  52. value &= 0xF;
  53. mask &= 0xF;
  54. return (value & mask) == mask;
  55. }
  56. /**
  57. * @brief Tap keycode, with no mods
  58. *
  59. * @param kc keycode to use
  60. */
  61. void tap_code16_nomods(uint16_t kc) {
  62. uint8_t temp_mod = get_mods();
  63. clear_mods();
  64. clear_oneshot_mods();
  65. tap_code16(kc);
  66. set_mods(temp_mod);
  67. }
  68. #ifdef I2C_SCANNER_ENABLE
  69. # include "i2c_master.h"
  70. # include "debug.h"
  71. # ifndef I2C_SCANNER_TIMEOUT
  72. # define I2C_SCANNER_TIMEOUT 50
  73. # endif
  74. i2c_status_t i2c_start_bodge(uint8_t address, uint16_t timeout) {
  75. i2c_start(address);
  76. // except on ChibiOS where the only way is do do "something"
  77. uint8_t data = 0;
  78. return i2c_readReg(address, 0, &data, sizeof(data), I2C_SCANNER_TIMEOUT);
  79. }
  80. # define i2c_start i2c_start_bodge
  81. void do_scan(void) {
  82. uint8_t nDevices = 0;
  83. dprintf("Scanning...\n");
  84. for (uint8_t address = 1; address < 127; address++) {
  85. // The i2c_scanner uses the return value of
  86. // i2c_start to see if a device did acknowledge to the address.
  87. i2c_status_t error = i2c_start(address << 1, I2C_SCANNER_TIMEOUT);
  88. if (error == I2C_STATUS_SUCCESS) {
  89. i2c_stop();
  90. xprintf(" I2C device found at address 0x%02X\n", I2C_SCANNER_TIMEOUT);
  91. nDevices++;
  92. } else {
  93. // dprintf(" Unknown error (%u) at address 0x%02X\n", error, address);
  94. }
  95. }
  96. if (nDevices == 0)
  97. xprintf("No I2C devices found\n");
  98. else
  99. xprintf("done\n");
  100. }
  101. uint16_t scan_timer = 0;
  102. void matrix_scan_i2c(void) {
  103. if (timer_elapsed(scan_timer) > 5000) {
  104. do_scan();
  105. scan_timer = timer_read();
  106. }
  107. }
  108. void keyboard_post_init_i2c(void) {
  109. i2c_init();
  110. scan_timer = timer_read();
  111. }
  112. #endif
  113. #if defined(AUTOCORRECT_ENABLE)
  114. # if defined(AUDIO_ENABLE)
  115. # ifdef USER_SONG_LIST
  116. float autocorrect_song[][2] = SONG(MARIO_GAMEOVER);
  117. # else
  118. float autocorrect_song[][2] = SONG(PLOVER_GOODBYE_SOUND);
  119. # endif
  120. # endif
  121. bool apply_autocorrect(uint8_t backspaces, const char *str) {
  122. if (layer_state_is(_GAMEPAD)) {
  123. return false;
  124. }
  125. // TO-DO use unicode stuff for this. Will probably have to reverse engineer
  126. // send string to get working properly, to send char string.
  127. # if defined(AUDIO_ENABLE)
  128. PLAY_SONG(autocorrect_song);
  129. # endif
  130. return true;
  131. }
  132. #endif
  133. #if defined(CAPS_WORD_ENABLE) && !defined(NO_ACTION_ONESHOT)
  134. void oneshot_locked_mods_changed_user(uint8_t mods) {
  135. if (mods & MOD_MASK_SHIFT) {
  136. del_mods(MOD_MASK_SHIFT);
  137. set_oneshot_locked_mods(~MOD_MASK_SHIFT & get_oneshot_locked_mods());
  138. caps_word_on();
  139. }
  140. }
  141. #endif