You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
10 KiB

  1. /* Copyright 2021 Gun Pinyo
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include QMK_KEYBOARD_H
  17. extern keymap_config_t keymap_config;
  18. enum planck_layers {
  19. LY_0000, LY_0001, LY_0010, LY_0011,
  20. LY_0100, LY_0101, LY_0110, LY_0111,
  21. LY_1000, LY_1001, LY_1010, LY_1011,
  22. LY_1100, LY_1101, LY_1110, LY_1111,
  23. LY_THAI_A, LY_THAI_B, LY_THAI_C,
  24. LY_SANDBOX, LY_STICK,
  25. };
  26. enum planck_keycodes {
  27. MIN_KC = SAFE_RANGE,
  28. FUNC_A, FUNC_B, FUNC_C, FUNC_D,
  29. SANDBOX, STICK,
  30. LTHAI_A, LTHAI_B, LTHAI_C,
  31. LSW0110, LSW1111, LSW0100,
  32. USER_NAME, USER_EMAIL,
  33. MAX_KC,
  34. DYNAMIC_MACRO_RANGE,
  35. };
  36. #define KC_L2_0 KC_LSFT
  37. #define KC_L3_0 KC_LCTL
  38. #define KC_L3_1 KC_LALT
  39. #define KC_L3_2 KC_LGUI
  40. #define KC_R2_1 FUNC_A
  41. #define KC_R2_2 FUNC_B
  42. #define KC_R2_3 FUNC_C
  43. #define KC_R2_4 FUNC_D
  44. #define KC_R2_5 KC_RSFT
  45. #define KC_R3_0 KC_R2_4
  46. #define KC_R3_1 KC_SPC
  47. #define LAYOUT_gunp( k00, k01, k02, k03, k04, k05, \
  48. k10, k11, k12, k13, k14, k15, \
  49. k20, k21, k22, k23, k24, k25, \
  50. k30, k31, k32, k33, k34, k35) \
  51. LAYOUT_ortho_4x12( \
  52. k00,k01,k02,k03,k04,k05, LSW0110, KC_LEFT, KC_BSPC, KC_RIGHT,XXXXXXX, XXXXXXX,\
  53. k10,k11,k12,k13,k14,k15, LSW1111, LTHAI_A, LTHAI_B, LTHAI_C, XXXXXXX, XXXXXXX,\
  54. k20,k21,k22,k23,k24,k25, LSW0100, KC_R2_1, KC_R2_2, KC_R2_3, KC_R2_4, KC_R2_5,\
  55. k30,k31,k32,k33,k34,k35, KC_R3_0, KC_R3_1, KC_ENT, KC_RGUI, KC_RALT, KC_RCTL)
  56. #define UNUSED_LAYER LAYOUT_gunp(\
  57. XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\
  58. XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\
  59. XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\
  60. XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX),
  61. #define F1_F12_LAYER(M) LAYOUT_gunp(\
  62. S(M(KC_F7 )), S(M(KC_F8 )), M(KC_F7 ), M(KC_F8 ), M(KC_F9 ), S(M(KC_F9 )),\
  63. S(M(KC_F4 )), S(M(KC_F5 )), M(KC_F4 ), M(KC_F5 ), M(KC_F6 ), S(M(KC_F6 )),\
  64. S(M(KC_F1 )), S(M(KC_F2 )), M(KC_F1 ), M(KC_F2 ), M(KC_F3 ), S(M(KC_F3 )),\
  65. S(M(KC_F10)), S(M(KC_F11)), M(KC_F10), M(KC_F11), M(KC_F12), S(M(KC_F12))),
  66. #define MC(kc) LCTL(kc)
  67. #define MA(kc) LALT(kc)
  68. #define MG(kc) LGUI(kc)
  69. #define MSC(kc) LSFT(LCTL(kc))
  70. const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  71. [LY_0000] = LAYOUT_ortho_4x12(
  72. KC_PGUP, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_K, KC_TAB,
  73. KC_PGDN, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, STICK,
  74. KC_L2_0, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_M,
  75. KC_R2_1, KC_R2_2, KC_R2_3, KC_UP, KC_R2_5,
  76. KC_L3_0, KC_L3_1, KC_L3_2, KC_ESCAPE, KC_BSPC, KC_ENTER,
  77. KC_R3_0, KC_R3_1, KC_PSCR, KC_LEFT, KC_DOWN, KC_RIGHT
  78. ),
  79. [LY_1000] = LAYOUT_gunp(
  80. XXXXXXX, KC_PERC, KC_QUES, KC_EXLM, KC_GRV, XXXXXXX,
  81. XXXXXXX, KC_AT, KC_COMM, KC_DOT, KC_QUOT, KC_EQL,
  82. KC_L2_0, KC_DLR, KC_SCLN, KC_COLN, KC_DQUO, KC_UNDS,
  83. KC_L3_0, KC_L3_1, KC_L3_2, XXXXXXX, XXXXXXX, XXXXXXX
  84. ),
  85. [LY_0010] = LAYOUT_gunp(
  86. XXXXXXX, KC_AMPR, KC_PIPE, KC_TILD, KC_CIRC, XXXXXXX,
  87. XXXXXXX, KC_LCBR, KC_LBRC, KC_LPRN, KC_LT, KC_SLSH,
  88. KC_L2_0, KC_RCBR, KC_RBRC, KC_RPRN, KC_GT, KC_BSLS,
  89. KC_L3_0, KC_L3_1, KC_L3_2, XXXXXXX, XXXXXXX, XXXXXXX
  90. ),
  91. [LY_1010] = LAYOUT_gunp(
  92. XXXXXXX, KC_HASH, KC_7, KC_8, KC_9, XXXXXXX,
  93. XXXXXXX, KC_ASTR, KC_4, KC_5, KC_6, KC_PLUS,
  94. KC_L2_0, KC_0, KC_1, KC_2, KC_3, KC_MINS,
  95. KC_L3_0, KC_L3_1, KC_L3_2, XXXXXXX, XXXXXXX, XXXXXXX
  96. ),
  97. [LY_0100] = LAYOUT_gunp(
  98. XXXXXXX, MC(KC_G), KC_HOME, KC_UP, KC_END, MC(KC_UP),
  99. XXXXXXX, KC_PGUP, KC_LEFT, KC_DOWN, KC_RIGHT, MC(KC_DOWN),
  100. XXXXXXX, KC_PGDN, MC(KC_S), MC(KC_A), MC(KC_Z), MSC(KC_Z),
  101. XXXXXXX, XXXXXXX, MC(KC_LEFT), MC(KC_F), MC(KC_RIGHT), XXXXXXX
  102. ),
  103. [LY_1100] = LAYOUT_gunp(
  104. XXXXXXX, MSC(KC_G), S(KC_HOME), S(KC_UP), S(KC_END), MSC(KC_UP),
  105. XXXXXXX, S(KC_PGUP), S(KC_LEFT), S(KC_DOWN), S(KC_RIGHT), MSC(KC_DOWN),
  106. XXXXXXX, S(KC_PGDN), MC(KC_X), MC(KC_C), MC(KC_V), MC(KC_L),
  107. XXXXXXX, XXXXXXX, MSC(KC_LEFT), MC(KC_R), MSC(KC_RIGHT), XXXXXXX
  108. ),
  109. [LY_0110] = F1_F12_LAYER()
  110. [LY_1110] = F1_F12_LAYER(MG)
  111. [LY_0001] = LAYOUT_gunp(
  112. MC(KC_H), MC(KC_0), MSC(KC_PGUP), KC_BRIU, MSC(KC_PGDN), KC_VOLU,
  113. MSC(KC_T), MC(KC_PLUS), MC(KC_PGUP), KC_BRID, MC(KC_PGDN), KC_VOLD,
  114. OSM(MOD_LSFT), MC(KC_MINS), MA(KC_LEFT), MC(KC_T), MA(KC_RIGHT), KC_MUTE,
  115. OSM(MOD_LCTL), OSM(MOD_LALT), OSM(MOD_LGUI), MC(KC_W), KC_DELETE, KC_APP
  116. ),
  117. [LY_1101] = LAYOUT_gunp(
  118. SANDBOX, XXXXXXX, AU_TOG, QK_LOCK, RGB_TOG, QK_BOOT,
  119. KC_WAKE, KC_CAPS, USER_NAME, USER_EMAIL, RGB_MOD, DB_TOGG,
  120. KC_SLEP, KC_NUM, DM_REC1, DM_PLY1, XXXXXXX, EE_CLR,
  121. KC_PWR, KC_SCRL, DM_REC2, DM_PLY2, DM_RSTP, KC_INSERT
  122. ),
  123. [LY_1111] = LAYOUT_gunp(
  124. KC_ACL1, KC_ACL0, KC_WH_L, KC_MS_U, KC_WH_R, KC_WH_U,
  125. KC_ACL2, XXXXXXX, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D,
  126. KC_MPRV, KC_BTN5, KC_MRWD, KC_MPLY, KC_MFFD, KC_BTN3,
  127. KC_MNXT, KC_BTN4, KC_PAUSE, KC_MSTP, KC_BTN1, KC_BTN2
  128. ),
  129. [LY_0111] = UNUSED_LAYER
  130. [LY_1011] = UNUSED_LAYER
  131. [LY_1001] = UNUSED_LAYER
  132. [LY_0101] = UNUSED_LAYER
  133. [LY_0011] = UNUSED_LAYER
  134. /* mapping from US QWERTY to TH Kedmanee */
  135. [LY_THAI_A] = LAYOUT_gunp(
  136. S(KC_G), KC_PIPE, KC_8, KC_COMM, S(KC_A), KC_QUES,
  137. S(KC_I), KC_SCLN, KC_QUOT, KC_O, KC_I, KC_RBRC,
  138. S(KC_P), S(KC_T), KC_M, KC_P, KC_EQL, KC_COLN,
  139. KC_LT, S(KC_S), S(KC_R), KC_GT, KC_R, KC_A
  140. ),
  141. [LY_THAI_B] = LAYOUT_gunp(
  142. S(KC_N), S(KC_H), KC_J, KC_H, S(KC_U), S(KC_J),
  143. S(KC_F), KC_C, KC_G, KC_K, KC_Y, KC_T,
  144. KC_DOT, KC_W, KC_B, KC_U, KC_7, KC_N,
  145. KC_1, S(KC_B), S(KC_Y), KC_E, KC_6, KC_CIRC
  146. ),
  147. [LY_THAI_C] = LAYOUT_gunp(
  148. KC_4, KC_BSLS, KC_MINS, S(KC_V), S(KC_E), S(KC_D),
  149. KC_5, KC_0, KC_D, KC_V, KC_F, KC_9,
  150. S(KC_L), S(KC_K), KC_L, KC_S, KC_LBRC, KC_X,
  151. S(KC_O), KC_Q, KC_LCBR, S(KC_C), KC_Z, KC_SLSH
  152. ),
  153. [LY_SANDBOX] = LAYOUT_ortho_4x12(
  154. KC_LCBR, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_K, KC_RCBR,
  155. KC_LBRC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_RBRC,
  156. KC_LPRN,KC_Z,KC_X,KC_C,KC_V,KC_B,KC_M,KC_COMM,KC_DOT,KC_SCLN,KC_COLN,KC_RPRN,
  157. KC_LT , KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_GT
  158. ),
  159. [LY_STICK] = UNUSED_LAYER // as a gateway to other persistant layers
  160. };
  161. #define NUM_LANGS 2
  162. #define LANG_ENG 0
  163. #define LANG_THAI 1
  164. uint16_t cur_layer = LY_0000;
  165. uint16_t cur_lang = LANG_ENG;
  166. bool is_layer_persistant = false;
  167. void change_layer(uint16_t new_layer) {
  168. if(cur_layer != new_layer) {
  169. layer_off(cur_layer);
  170. layer_on(new_layer);
  171. cur_layer = new_layer;
  172. }
  173. }
  174. void change_lang(uint16_t lang) {
  175. while(lang != cur_lang) {
  176. SEND_STRING(SS_LGUI(" "));
  177. cur_lang = (cur_lang + 1) % NUM_LANGS;
  178. }
  179. }
  180. void user_panic(void) {
  181. SEND_STRING("Planck Keyboard: User Panic!");
  182. }
  183. void update_env_thai(void) {
  184. if(LY_THAI_A <= cur_layer && cur_layer <= LY_THAI_C) {
  185. change_lang(LANG_THAI);
  186. } else {
  187. change_lang(LANG_ENG);
  188. }
  189. }
  190. uint16_t get_persistant_layer_from_keycode(uint16_t keycode) {
  191. switch(keycode) {
  192. case FUNC_A: return LY_1000;
  193. case FUNC_B: return LY_1010;
  194. case FUNC_C: return LY_0010;
  195. case FUNC_D: return LY_0000;
  196. case LTHAI_A: return LY_THAI_A;
  197. case LTHAI_B: return LY_THAI_B;
  198. case LTHAI_C: return LY_THAI_C;
  199. case LSW0110: return LY_0110;
  200. case LSW1111: return LY_1111;
  201. case LSW0100: return LY_0100;
  202. }
  203. return 0; // this line is unreachable but be here to make the complier happy
  204. }
  205. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  206. if(!is_layer_persistant && FUNC_A <= keycode && keycode <= FUNC_D) {
  207. uint16_t mask = 1 << (3 - (keycode - FUNC_A));
  208. uint16_t cur_layer_code = cur_layer - LY_0000;
  209. if(!(LY_0000 <= cur_layer && cur_layer <= LY_1111))
  210. user_panic();
  211. if(!(cur_layer_code & mask) == record->event.pressed)
  212. change_layer((mask ^ cur_layer_code) + LY_0000);
  213. return false;
  214. }
  215. if(!(record->event.pressed))
  216. return !(MIN_KC <= keycode && keycode <= MAX_KC);
  217. switch(keycode) {
  218. case USER_NAME:
  219. SEND_STRING("Gun Pinyo");
  220. return false;
  221. case USER_EMAIL:
  222. SEND_STRING("gunpinyo@gmail.com");
  223. return false;
  224. case SANDBOX:
  225. case STICK:
  226. change_layer(keycode == STICK ? LY_STICK : LY_SANDBOX);
  227. change_lang(LANG_ENG);
  228. is_layer_persistant = true;
  229. return false;
  230. case FUNC_A: case FUNC_B: case FUNC_C: case FUNC_D:
  231. case LTHAI_A: case LTHAI_B: case LTHAI_C:
  232. case LSW0110: case LSW1111: case LSW0100:
  233. if(is_layer_persistant) {
  234. change_layer(get_persistant_layer_from_keycode(keycode));
  235. update_env_thai();
  236. // `FUNC_D` resets the layer configuration when `is_layer_persistant`
  237. is_layer_persistant = keycode != FUNC_D;
  238. if(!is_layer_persistant) {
  239. clear_keyboard();
  240. layer_clear();
  241. }
  242. }
  243. return false;
  244. }
  245. return true;
  246. }
  247. #ifdef RGB_MATRIX_ENABLE
  248. bool rgb_matrix_indicators_user(void) {
  249. // `42` is the index of the middle light at the bottom row (in planck light)
  250. // it is disabled because it does not have a cover, hence irritates my eyes
  251. rgb_matrix_set_color(42, 0, 0, 0);
  252. return false;
  253. }
  254. #endif
  255. #ifdef AUDIO_ENABLE
  256. float tone_startup[][2] = SONG(STARTUP_SOUND);
  257. float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
  258. float tone_ly_normal[][2] = SONG(QWERTY_SOUND);
  259. float tone_ly_spacial[][2] = SONG(DVORAK_SOUND);
  260. float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
  261. #endif
  262. void startup_user() {
  263. #ifdef AUDIO_ENABLE
  264. PLAY_SONG(tone_startup);
  265. #endif
  266. }
  267. void shutdown_user() {
  268. #ifdef AUDIO_ENABLE
  269. PLAY_SONG(tone_goodbye);
  270. stop_all_notes();
  271. #endif
  272. }