annepro2.c (8977B)
1 /* Copyright 2021 OpenAnnePro community 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 17 #include "hal.h" 18 #include "annepro2.h" 19 #include "annepro2_ble.h" 20 #include "spi_master.h" 21 #include "ap2_led.h" 22 #include "protocol.h" 23 24 #define RAM_MAGIC_LOCATION 0x20001ffc 25 #define IAP_MAGIC_VALUE 0x0000fab2 26 27 static const SerialConfig led_uart_init_config = { 28 .speed = 115200, 29 }; 30 31 #ifndef LED_UART_BAUD_RATE 32 # define LED_UART_BAUD_RATE 115200 33 #endif // LED_UART_BAUD_RATE 34 35 static const SerialConfig led_uart_runtine_config = { 36 .speed = LED_UART_BAUD_RATE, 37 }; 38 39 static const SerialConfig ble_uart_config = { 40 .speed = 115200, 41 }; 42 43 static uint8_t led_mcu_wakeup[11] = {0x7b, 0x10, 0x43, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x02}; 44 45 ble_capslock_t ble_capslock = {._dummy = {0}, .caps_lock = false}; 46 47 #ifdef RGB_MATRIX_ENABLE 48 static uint8_t led_enabled = 1; 49 #endif 50 51 void mcu_reset(void) { 52 __disable_irq(); 53 NVIC_SystemReset(); 54 } 55 56 void bootloader_jump(void) { 57 // Send msg to shine to boot into IAP 58 ap2_set_IAP(); 59 60 // wait for shine to boot into IAP 61 wait_ms(15); 62 63 // Load ble into IAP 64 annepro2_ble_bootload(); 65 wait_ms(15); 66 67 // Magic key to set keyboard to IAP 68 // It’s from reversing original boot loader 69 // If value is that it stays in boot loader aka IAP 70 *((uint32_t *)RAM_MAGIC_LOCATION) = IAP_MAGIC_VALUE; 71 72 // Load the main MCU into IAP 73 __disable_irq(); 74 NVIC_SystemReset(); 75 } 76 77 void keyboard_pre_init_kb(void) { 78 // Start LED UART 79 sdStart(&SD0, &led_uart_init_config); 80 /* Let the LED chip settle a bit before switching the mode. 81 * That helped at least one person. */ 82 wait_ms(15); 83 sdWrite(&SD0, led_mcu_wakeup, sizeof(led_mcu_wakeup)); 84 85 // wait to receive response from wakeup 86 wait_ms(15); 87 88 proto_init(&proto, led_command_callback); 89 90 // loop to clear out receive buffer from shine wakeup 91 while (!sdGetWouldBlock(&SD0)) sdGet(&SD0); 92 93 sdStart(&SD0, &led_uart_runtine_config); 94 keyboard_pre_init_user(); 95 } 96 97 void keyboard_post_init_kb(void) { 98 // Start BLE UART 99 sdStart(&SD1, &ble_uart_config); 100 annepro2_ble_startup(); 101 102 // Give the send uart thread some time to 103 // send out the queue before we read back 104 wait_ms(100); 105 106 // loop to clear out receive buffer from ble wakeup 107 while (!sdGetWouldBlock(&SD1)) sdGet(&SD1); 108 109 #ifdef RGB_MATRIX_ENABLE 110 ap2_led_set_manual_control(1); 111 ap2_led_enable(); 112 #endif 113 114 keyboard_post_init_user(); 115 } 116 117 void matrix_scan_kb(void) { 118 // if there's stuff on the ble serial buffer 119 // read it into the capslock struct 120 while (!sdGetWouldBlock(&SD1)) { 121 sdReadTimeout(&SD1, (uint8_t *)&ble_capslock, sizeof(ble_capslock_t), 10); 122 } 123 124 /* While there's data from LED keyboard sent - read it. */ 125 while (!sdGetWouldBlock(&SD0)) { 126 uint8_t byte = sdGet(&SD0); 127 proto_consume(&proto, byte); 128 } 129 130 131 matrix_scan_user(); 132 } 133 134 bool process_record_kb(uint16_t keycode, keyrecord_t *record) { 135 if (record->event.pressed) { 136 if (ap2_led_status.matrix_enabled && ap2_led_status.is_reactive) { 137 ap2_led_forward_keypress(record->event.key.row, record->event.key.col); 138 } 139 140 const ap2_led_t blue = { 141 .p.blue = 0xff, 142 .p.red = 0x00, 143 .p.green = 0x00, 144 .p.alpha = 0xff, 145 }; 146 147 switch (keycode) { 148 case KC_AP2_BT1: 149 annepro2_ble_broadcast(0); 150 /* FIXME: This hardcodes col/row position */ 151 ap2_led_blink(record->event.key.row, record->event.key.col, blue, 8, 50); 152 return false; 153 154 case KC_AP2_BT2: 155 annepro2_ble_broadcast(1); 156 ap2_led_blink(record->event.key.row, record->event.key.col, blue, 8, 50); 157 return false; 158 159 case KC_AP2_BT3: 160 annepro2_ble_broadcast(2); 161 ap2_led_blink(record->event.key.row, record->event.key.col, blue, 8, 50); 162 return false; 163 164 case KC_AP2_BT4: 165 annepro2_ble_broadcast(3); 166 ap2_led_blink(record->event.key.row, record->event.key.col, blue, 8, 50); 167 return false; 168 169 case KC_AP2_USB: 170 annepro2_ble_disconnect(); 171 return false; 172 173 case KC_AP2_BT_UNPAIR: 174 annepro2_ble_unpair(); 175 return false; 176 177 case KC_AP_LED_OFF: 178 ap2_led_disable(); 179 break; 180 181 case KC_AP_LED_ON: 182 if (ap2_led_status.matrix_enabled) { 183 ap2_led_next_profile(); 184 } else { 185 ap2_led_enable(); 186 } 187 ap2_led_reset_foreground_color(); 188 break; 189 190 case KC_AP_LED_TOG: 191 if (ap2_led_status.matrix_enabled) { 192 ap2_led_disable(); 193 } else { 194 ap2_led_enable(); 195 ap2_led_reset_foreground_color(); 196 } 197 break; 198 199 case KC_AP_LED_NEXT_PROFILE: 200 ap2_led_next_profile(); 201 ap2_led_reset_foreground_color(); 202 break; 203 204 case KC_AP_LED_PREV_PROFILE: 205 ap2_led_prev_profile(); 206 ap2_led_reset_foreground_color(); 207 break; 208 209 case KC_AP_LED_NEXT_INTENSITY: 210 ap2_led_next_intensity(); 211 ap2_led_reset_foreground_color(); 212 return false; 213 214 case KC_AP_LED_SPEED: 215 ap2_led_next_animation_speed(); 216 ap2_led_reset_foreground_color(); 217 return false; 218 #ifdef RGB_MATRIX_ENABLE 219 case QK_RGB_MATRIX_TOGGLE: 220 if(rgb_matrix_is_enabled()) ap2_led_disable(); 221 else ap2_led_enable(); 222 return true; 223 224 case KC_AP_RGB_VAI: 225 if (record->event.pressed) { 226 if (get_mods() & MOD_MASK_SHIFT) { 227 rgb_matrix_increase_hue(); 228 return false; 229 } else if (get_mods() & MOD_MASK_CTRL) { 230 rgb_matrix_decrease_hue(); 231 return false; 232 } else { 233 rgb_matrix_increase_val(); 234 } 235 } 236 return true; 237 238 case KC_AP_RGB_VAD: 239 if (record->event.pressed) { 240 if (get_mods() & MOD_MASK_SHIFT) { 241 rgb_matrix_increase_sat(); 242 return false; 243 } else if (get_mods() & MOD_MASK_CTRL) { 244 rgb_matrix_decrease_sat(); 245 return false; 246 } else { 247 rgb_matrix_decrease_val(); 248 } 249 } 250 return true; 251 252 case KC_AP_RGB_TOG: 253 if (record->event.pressed) { 254 if (get_mods() & MOD_MASK_SHIFT) { 255 rgb_matrix_increase_speed(); 256 return false; 257 } else if (get_mods() & MOD_MASK_CTRL) { 258 rgb_matrix_decrease_speed(); 259 return false; 260 } else { 261 if (led_enabled) { 262 ap2_led_disable(); 263 rgb_matrix_disable(); 264 led_enabled = 0; 265 } else { 266 ap2_led_enable(); 267 rgb_matrix_enable(); 268 led_enabled = 1; 269 } 270 return true; 271 } 272 } 273 return true; 274 275 case KC_AP_RGB_MOD: 276 if (record->event.pressed) { 277 if (get_mods() & MOD_MASK_CTRL) { 278 rgb_matrix_step_reverse(); 279 return false; 280 } else { 281 rgb_matrix_step(); 282 } 283 } 284 return true; 285 #endif 286 287 default: 288 break; 289 } 290 } 291 return process_record_user(keycode, record); 292 }