unicorne.c (5198B)
1 /* Copyright 2021 Yang Hu 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 "unicorne.h" 17 #include "i2c_master.h" 18 19 // Custom i2c init to enable internal pull up resistor for i2c. 20 void i2c_init(void) { 21 static bool is_initialised = false; 22 if (!is_initialised) { 23 is_initialised = true; 24 25 // Try releasing special pins for a short time 26 palSetLineMode(I2C1_SCL_PIN, PAL_MODE_INPUT); 27 palSetLineMode(I2C1_SDA_PIN, PAL_MODE_INPUT); 28 29 chThdSleepMilliseconds(10); 30 // Use internal pull up since we do not have pull up on i2c pins in v1 design. 31 palSetLineMode(I2C1_SCL_PIN, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); 32 palSetLineMode(I2C1_SDA_PIN, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); 33 } 34 } 35 36 #ifdef OLED_ENABLE 37 // OLED shared code 38 // The oled is vertical. Need to rotate 270 degrees. 39 __attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) { return OLED_ROTATION_270; } 40 41 // Render layer status on OLED. To be re-implemented by keymaps since layers are 42 // defined there. 43 __attribute__((weak)) void oled_render_layer(void) { return; } 44 45 // Oneshot mods status 46 uint8_t osmods; 47 48 __attribute__((weak)) void oled_render_mods(void) { 49 static const char PROGMEM ctrl[] = {0xb6, 0xb7, 10, 0xd6, 0xd7, 10, 0x20, 0x20, 10, 0}; 50 static const char PROGMEM shift[] = {0x87, 0x88, 0x89, 10, 0xa7, 0xa8, 0xa9, 10, 0xc7, 0xc8, 0xc9, 10, 0}; 51 static const char PROGMEM alt[] = {0x84, 0x85, 0x86, 10, 0xa4, 0xa5, 0xa6, 10, 0xc4, 0xc5, 0xc6, 10, 0}; 52 static const char PROGMEM ctrl_alt[] = {0xb6, 0xb7, 0x84, 0x85, 0x86, 0xd6, 0xd7, 0xa4, 0xa5, 0xa6, 0x20, 0x20, 0xc4, 0xc5, 0xc6, 0}; 53 54 static const char PROGMEM ctrl_shift[] = {0xb6, 0xb7, 0x87, 0x88, 0x89, 0xd6, 0xd7, 0xa7, 0xa8, 0xa9, 0x20, 0x20, 0xc7, 0xc8, 0xc9, 0}; 55 static const char PROGMEM c_a_shift[] = {0xb6, 0xb7, 0x84, 0x85, 0x86, 0xd6, 0xd7, 0xa4, 0xa5, 0xa6, 0x20, 0x20, 0xc4, 0xc5, 0xc6, 0x87, 0x88, 0x89, 10, 0xa7, 0xa8, 0xa9, 10, 0xc7, 0xc8, 0xc9, 10, 0}; 56 // Now check mod status and render. 57 static uint8_t mods; 58 mods = get_mods() | osmods; 59 if ((mods & MOD_MASK_CTRL) && (mods & MOD_MASK_ALT) && (mods & MOD_MASK_SHIFT)) { 60 oled_write_P(c_a_shift, false); 61 } else if ((mods & MOD_MASK_CTRL) && (mods & MOD_MASK_ALT)) { 62 oled_write_P(ctrl_alt, false); 63 } else if ((mods & MOD_MASK_CTRL) && (mods & MOD_MASK_SHIFT)) { 64 oled_write_P(ctrl_shift, false); 65 } else if ((mods & MOD_MASK_SHIFT) && (mods & MOD_MASK_ALT)) { 66 oled_write_P(alt, false); 67 oled_write_P(shift, false); 68 } else if (mods & MOD_MASK_CTRL) { 69 oled_write_P(ctrl, false); 70 } else if (mods & MOD_MASK_ALT) { 71 oled_write_P(alt, false); 72 } else if (mods & MOD_MASK_SHIFT) { 73 oled_write_P(shift, false); 74 } else { 75 for (int i = 0; i < 6; ++i) { 76 oled_write_ln(" ", false); 77 } 78 } 79 return; 80 } 81 82 void oneshot_mods_changed_user(uint8_t mods) { osmods = mods; } 83 84 // Call this from "led_update_user" and use `led_state.caps_lock` to check 85 // the status of capslock. 86 __attribute__((weak)) void oled_render_capslock(bool caps_on) { 87 static const char PROGMEM capslock_logo[] = {0x9c, 0x9d, 0x9e, 0x9f, 10, 0xbc, 0xbd, 0xbe, 0xbf, 10, 0xdc, 0xdd, 0xde, 0xdf, 10, 0}; 88 if (caps_on) { 89 oled_write_P(capslock_logo, false); 90 } else { 91 for (int i = 0; i < 3; ++i) { 92 oled_write_ln(" ", false); 93 } 94 } 95 } 96 97 char keylog_str[24] = {}; 98 99 const char code_to_name[60] = {' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\', '#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '}; 100 101 void set_keylog(uint16_t keycode, keyrecord_t *record) { 102 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { 103 keycode = keycode & 0xFF; 104 } 105 } 106 107 __attribute__((weak)) void oled_render_keylog(void) { oled_write(keylog_str, false); } 108 109 // Keymaps can override this function 110 __attribute__((weak)) bool oled_task_kb(void) { 111 if (!oled_task_user()) { return false; } 112 /* oled_render_keylog(); */ 113 oled_render_layer(); 114 oled_render_mods(); 115 led_t led_state = host_keyboard_led_state(); 116 oled_render_capslock(led_state.caps_lock); 117 return true; 118 } 119 #endif