292 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			292 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Copyright 2021 OpenAnnePro community
 | ||
|  *
 | ||
|  * This program is free software: you can redistribute it and/or modify
 | ||
|  * it under the terms of the GNU General Public License as published by
 | ||
|  * the Free Software Foundation, either version 2 of the License, or
 | ||
|  * (at your option) any later version.
 | ||
|  *
 | ||
|  * This program is distributed in the hope that it will be useful,
 | ||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | ||
|  * GNU General Public License for more details.
 | ||
|  *
 | ||
|  * You should have received a copy of the GNU General Public License
 | ||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||
|  */
 | ||
| 
 | ||
| #include "hal.h"
 | ||
| #include "annepro2.h"
 | ||
| #include "annepro2_ble.h"
 | ||
| #include "spi_master.h"
 | ||
| #include "ap2_led.h"
 | ||
| #include "protocol.h"
 | ||
| 
 | ||
| #define RAM_MAGIC_LOCATION 0x20001ffc
 | ||
| #define IAP_MAGIC_VALUE 0x0000fab2
 | ||
| 
 | ||
| static const SerialConfig led_uart_init_config = {
 | ||
|     .speed = 115200,
 | ||
| };
 | ||
| 
 | ||
| #ifndef LED_UART_BAUD_RATE
 | ||
| #    define LED_UART_BAUD_RATE 115200
 | ||
| #endif  // LED_UART_BAUD_RATE
 | ||
| 
 | ||
| static const SerialConfig led_uart_runtine_config = {
 | ||
|     .speed = LED_UART_BAUD_RATE,
 | ||
| };
 | ||
| 
 | ||
| static const SerialConfig ble_uart_config = {
 | ||
|     .speed = 115200,
 | ||
| };
 | ||
| 
 | ||
| static uint8_t led_mcu_wakeup[11] = {0x7b, 0x10, 0x43, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x02};
 | ||
| 
 | ||
| ble_capslock_t ble_capslock = {._dummy = {0}, .caps_lock = false};
 | ||
| 
 | ||
| #ifdef RGB_MATRIX_ENABLE
 | ||
| static uint8_t led_enabled = 1;
 | ||
| #endif
 | ||
| 
 | ||
| void mcu_reset(void) {
 | ||
|     __disable_irq();
 | ||
|     NVIC_SystemReset();
 | ||
| }
 | ||
| 
 | ||
| void bootloader_jump(void) {
 | ||
|     // Send msg to shine to boot into IAP
 | ||
|     ap2_set_IAP();
 | ||
| 
 | ||
|     // wait for shine to boot into IAP
 | ||
|     wait_ms(15);
 | ||
| 
 | ||
|     // Load ble into IAP
 | ||
|     annepro2_ble_bootload();
 | ||
|     wait_ms(15);
 | ||
| 
 | ||
|     // Magic key to set keyboard to IAP
 | ||
|     // It’s from reversing original boot loader
 | ||
|     // If value is that it stays in boot loader aka IAP
 | ||
|     *((uint32_t *)RAM_MAGIC_LOCATION) = IAP_MAGIC_VALUE;
 | ||
| 
 | ||
|     // Load the main MCU into IAP
 | ||
|     __disable_irq();
 | ||
|     NVIC_SystemReset();
 | ||
| }
 | ||
| 
 | ||
| void keyboard_pre_init_kb(void) {
 | ||
|     // Start LED UART
 | ||
|     sdStart(&SD0, &led_uart_init_config);
 | ||
|     /* Let the LED chip settle a bit before switching the mode.
 | ||
|      * That helped at least one person. */
 | ||
|     wait_ms(15);
 | ||
|     sdWrite(&SD0, led_mcu_wakeup, sizeof(led_mcu_wakeup));
 | ||
| 
 | ||
|     // wait to receive response from wakeup
 | ||
|     wait_ms(15);
 | ||
| 
 | ||
|     proto_init(&proto, led_command_callback);
 | ||
| 
 | ||
|     // loop to clear out receive buffer from shine wakeup
 | ||
|     while (!sdGetWouldBlock(&SD0)) sdGet(&SD0);
 | ||
| 
 | ||
|     sdStart(&SD0, &led_uart_runtine_config);
 | ||
|     keyboard_pre_init_user();
 | ||
| }
 | ||
| 
 | ||
| void keyboard_post_init_kb(void) {
 | ||
|     // Start BLE UART
 | ||
|     sdStart(&SD1, &ble_uart_config);
 | ||
|     annepro2_ble_startup();
 | ||
| 
 | ||
|     // Give the send uart thread some time to
 | ||
|     // send out the queue before we read back
 | ||
|     wait_ms(100);
 | ||
| 
 | ||
|     // loop to clear out receive buffer from ble wakeup
 | ||
|     while (!sdGetWouldBlock(&SD1)) sdGet(&SD1);
 | ||
| 
 | ||
|     #ifdef RGB_MATRIX_ENABLE
 | ||
|     ap2_led_set_manual_control(1);
 | ||
|     ap2_led_enable();
 | ||
|     #endif
 | ||
| 
 | ||
|     keyboard_post_init_user();
 | ||
| }
 | ||
| 
 | ||
| void matrix_scan_kb(void) {
 | ||
|     // if there's stuff on the ble serial buffer
 | ||
|     // read it into the capslock struct
 | ||
|     while (!sdGetWouldBlock(&SD1)) {
 | ||
|         sdReadTimeout(&SD1, (uint8_t *)&ble_capslock, sizeof(ble_capslock_t), 10);
 | ||
|     }
 | ||
| 
 | ||
|     /* While there's data from LED keyboard sent - read it. */
 | ||
|     while (!sdGetWouldBlock(&SD0)) {
 | ||
|         uint8_t byte = sdGet(&SD0);
 | ||
|         proto_consume(&proto, byte);
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     matrix_scan_user();
 | ||
| }
 | ||
| 
 | ||
| bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
 | ||
|     if (record->event.pressed) {
 | ||
|         if (ap2_led_status.matrix_enabled && ap2_led_status.is_reactive) {
 | ||
|             ap2_led_forward_keypress(record->event.key.row, record->event.key.col);
 | ||
|         }
 | ||
| 
 | ||
|         const ap2_led_t blue = {
 | ||
|             .p.blue  = 0xff,
 | ||
|             .p.red   = 0x00,
 | ||
|             .p.green = 0x00,
 | ||
|             .p.alpha = 0xff,
 | ||
|         };
 | ||
| 
 | ||
|         switch (keycode) {
 | ||
|             case KC_AP2_BT1:
 | ||
|                 annepro2_ble_broadcast(0);
 | ||
|                 /* FIXME: This hardcodes col/row position */
 | ||
|                 ap2_led_blink(record->event.key.row, record->event.key.col, blue, 8, 50);
 | ||
|                 return false;
 | ||
| 
 | ||
|             case KC_AP2_BT2:
 | ||
|                 annepro2_ble_broadcast(1);
 | ||
|                 ap2_led_blink(record->event.key.row, record->event.key.col, blue, 8, 50);
 | ||
|                 return false;
 | ||
| 
 | ||
|             case KC_AP2_BT3:
 | ||
|                 annepro2_ble_broadcast(2);
 | ||
|                 ap2_led_blink(record->event.key.row, record->event.key.col, blue, 8, 50);
 | ||
|                 return false;
 | ||
| 
 | ||
|             case KC_AP2_BT4:
 | ||
|                 annepro2_ble_broadcast(3);
 | ||
|                 ap2_led_blink(record->event.key.row, record->event.key.col, blue, 8, 50);
 | ||
|                 return false;
 | ||
| 
 | ||
|             case KC_AP2_USB:
 | ||
|                 annepro2_ble_disconnect();
 | ||
|                 return false;
 | ||
| 
 | ||
|             case KC_AP2_BT_UNPAIR:
 | ||
|                 annepro2_ble_unpair();
 | ||
|                 return false;
 | ||
| 
 | ||
|             case KC_AP_LED_OFF:
 | ||
|                 ap2_led_disable();
 | ||
|                 break;
 | ||
| 
 | ||
|             case KC_AP_LED_ON:
 | ||
|                 if (ap2_led_status.matrix_enabled) {
 | ||
|                     ap2_led_next_profile();
 | ||
|                 } else {
 | ||
|                     ap2_led_enable();
 | ||
|                 }
 | ||
|                 ap2_led_reset_foreground_color();
 | ||
|                 break;
 | ||
| 
 | ||
|             case KC_AP_LED_TOG:
 | ||
|                 if (ap2_led_status.matrix_enabled) {
 | ||
|                     ap2_led_disable();
 | ||
|                 } else {
 | ||
|                     ap2_led_enable();
 | ||
|                     ap2_led_reset_foreground_color();
 | ||
|                 }
 | ||
|                 break;
 | ||
| 
 | ||
|             case KC_AP_LED_NEXT_PROFILE:
 | ||
|                 ap2_led_next_profile();
 | ||
|                 ap2_led_reset_foreground_color();
 | ||
|                 break;
 | ||
| 
 | ||
|             case KC_AP_LED_PREV_PROFILE:
 | ||
|                 ap2_led_prev_profile();
 | ||
|                 ap2_led_reset_foreground_color();
 | ||
|                 break;
 | ||
| 
 | ||
|             case KC_AP_LED_NEXT_INTENSITY:
 | ||
|                 ap2_led_next_intensity();
 | ||
|                 ap2_led_reset_foreground_color();
 | ||
|                 return false;
 | ||
| 
 | ||
|             case KC_AP_LED_SPEED:
 | ||
|                 ap2_led_next_animation_speed();
 | ||
|                 ap2_led_reset_foreground_color();
 | ||
|                 return false;
 | ||
|             #ifdef RGB_MATRIX_ENABLE
 | ||
|             case QK_RGB_MATRIX_TOGGLE:
 | ||
|                 if(rgb_matrix_is_enabled()) ap2_led_disable();
 | ||
|                 else ap2_led_enable();
 | ||
|                 return true;
 | ||
| 
 | ||
|             case KC_AP_RGB_VAI:
 | ||
|                 if (record->event.pressed) {
 | ||
|                     if (get_mods() & MOD_MASK_SHIFT) {
 | ||
|                         rgb_matrix_increase_hue();
 | ||
|                         return false;
 | ||
|                     } else if (get_mods() & MOD_MASK_CTRL) {
 | ||
|                         rgb_matrix_decrease_hue();
 | ||
|                         return false;
 | ||
|                     } else {
 | ||
|                         rgb_matrix_increase_val();
 | ||
|                     }
 | ||
|                 }
 | ||
|                 return true;
 | ||
| 
 | ||
|             case KC_AP_RGB_VAD:
 | ||
|                 if (record->event.pressed) {
 | ||
|                     if (get_mods() & MOD_MASK_SHIFT) {
 | ||
|                         rgb_matrix_increase_sat();
 | ||
|                         return false;
 | ||
|                     } else if (get_mods() & MOD_MASK_CTRL) {
 | ||
|                         rgb_matrix_decrease_sat();
 | ||
|                         return false;
 | ||
|                     } else {
 | ||
|                         rgb_matrix_decrease_val();
 | ||
|                     }
 | ||
|                 }
 | ||
|                 return true;
 | ||
| 
 | ||
|             case KC_AP_RGB_TOG:
 | ||
|                 if (record->event.pressed) {
 | ||
|                     if (get_mods() & MOD_MASK_SHIFT) {
 | ||
|                         rgb_matrix_increase_speed();
 | ||
|                         return false;
 | ||
|                     } else if (get_mods() & MOD_MASK_CTRL) {
 | ||
|                         rgb_matrix_decrease_speed();
 | ||
|                         return false;
 | ||
|                     } else {
 | ||
|                         if (led_enabled) {
 | ||
|                             ap2_led_disable();
 | ||
|                             rgb_matrix_disable();
 | ||
|                             led_enabled = 0;
 | ||
|                         } else {
 | ||
|                             ap2_led_enable();
 | ||
|                             rgb_matrix_enable();
 | ||
|                             led_enabled = 1;
 | ||
|                         }
 | ||
|                         return true;
 | ||
|                     }
 | ||
|                 }
 | ||
|                 return true;
 | ||
| 
 | ||
|             case KC_AP_RGB_MOD:
 | ||
|                 if (record->event.pressed) {
 | ||
|                     if (get_mods() & MOD_MASK_CTRL) {
 | ||
|                         rgb_matrix_step_reverse();
 | ||
|                         return false;
 | ||
|                     } else {
 | ||
|                         rgb_matrix_step();
 | ||
|                     }
 | ||
|                 }
 | ||
|                 return true;
 | ||
|             #endif
 | ||
| 
 | ||
|             default:
 | ||
|                 break;
 | ||
|         }
 | ||
|     }
 | ||
|     return process_record_user(keycode, record);
 | ||
| }
 | 
