/* Copyright 2016-2017 Jack Humbert
*
* 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 "quantum.h"
#if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE)
#include "rgb.h"
#endif
#ifdef PROTOCOL_LUFA
#include "outputselect.h"
#endif
#ifndef BREATHING_PERIOD
#define BREATHING_PERIOD 6
#endif
#include "backlight.h"
extern backlight_config_t backlight_config;
#ifdef FAUXCLICKY_ENABLE
#include "fauxclicky.h"
#endif
#ifdef API_ENABLE
#include "api.h"
#endif
#ifdef MIDI_ENABLE
#include "process_midi.h"
#endif
#ifdef VELOCIKEY_ENABLE
#include "velocikey.h"
#endif
#ifdef HAPTIC_ENABLE
#include "haptic.h"
#endif
#ifdef ENCODER_ENABLE
#include "encoder.h"
#endif
#ifdef AUDIO_ENABLE
#ifndef GOODBYE_SONG
#define GOODBYE_SONG SONG(GOODBYE_SOUND)
#endif
#ifndef AG_NORM_SONG
#define AG_NORM_SONG SONG(AG_NORM_SOUND)
#endif
#ifndef AG_SWAP_SONG
#define AG_SWAP_SONG SONG(AG_SWAP_SOUND)
#endif
float goodbye_song[][2] = GOODBYE_SONG;
float ag_norm_song[][2] = AG_NORM_SONG;
float ag_swap_song[][2] = AG_SWAP_SONG;
#ifdef DEFAULT_LAYER_SONGS
float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS;
#endif
#endif
static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
switch (code) {
case QK_MODS ... QK_MODS_MAX:
break;
default:
return;
}
if (code & QK_LCTL)
f(KC_LCTL);
if (code & QK_LSFT)
f(KC_LSFT);
if (code & QK_LALT)
f(KC_LALT);
if (code & QK_LGUI)
f(KC_LGUI);
if (code < QK_RMODS_MIN) return;
if (code & QK_RCTL)
f(KC_RCTL);
if (code & QK_RSFT)
f(KC_RSFT);
if (code & QK_RALT)
f(KC_RALT);
if (code & QK_RGUI)
f(KC_RGUI);
}
static inline void qk_register_weak_mods(uint8_t kc) {
add_weak_mods(MOD_BIT(kc));
send_keyboard_report();
}
static inline void qk_unregister_weak_mods(uint8_t kc) {
del_weak_mods(MOD_BIT(kc));
send_keyboard_report();
}
static inline void qk_register_mods(uint8_t kc) {
add_weak_mods(MOD_BIT(kc));
send_keyboard_report();
}
static inline void qk_unregister_mods(uint8_t kc) {
del_weak_mods(MOD_BIT(kc));
send_keyboard_report();
}
void register_code16 (uint16_t code) {
if (IS_MOD(code) || code == KC_NO) {
do_code16 (code, qk_register_mods);
} else {
do_code16 (code, qk_register_weak_mods);
}
register_code (code);
}
void unregister_code16 (uint16_t code) {
unregister_code (code);
if (IS_MOD(code) || code == KC_NO) {
do_code16 (code, qk_unregister_mods);
} else {
do_code16 (code, qk_unregister_weak_mods);
}
}
void tap_code16(uint16_t code) {
register_code16(code);
#if TAP_CODE_DELAY > 0
wait_ms(TAP_CODE_DELAY);
#endif
unregister_code16(code);
}
__attribute__ ((weak))
bool process_action_kb(keyrecord_t *record) {
return true;
}
__attribute__ ((weak))
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
return process_record_user(keycode, record);
}
__attribute__ ((weak))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true;
}
void reset_keyboard(void) {
clear_keyboard();
#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
process_midi_all_notes_off();
#endif
#ifdef AUDIO_ENABLE
#ifndef NO_MUSIC_MODE
music_all_notes_off();
#endif
uint16_t timer_start = timer_read();
PLAY_SONG(goodbye_song);
shutdown_user();
while(timer_elapsed(timer_start) < 250)
wait_ms(1);
stop_all_notes();
#else
shutdown_user();
wait_ms(250);
#endif
#ifdef HAPTIC_ENABLE
haptic_shutdown();
#endif
// this is also done later in bootloader.c - not sure if it's neccesary here
#ifdef BOOTLOADER_CATERINA
*(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
#endif
bootloader_jump();
}
/* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
* Used to ensure that the correct keycode is released if the key is released.
*/
static bool grave_esc_was_shifted = false;
/* Convert record into usable keycode via the contained event. */
uint16_t get_record_keycode(keyrecord_t *record) {
return get_event_keycode(record->event);
}
/* Convert event into usable keycode. Checks the layer cache to ensure that it
* retains the correct keycode after a layer change, if the key is still pressed.
*/
uint16_t get_event_keycode(keyevent_t event) {
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
/* TODO: Use store_or_get_action() or a similar function. */
if (!disable_action_cache) {
uint8_t layer;
if (event.pressed) {
layer = layer_switch_get_layer(event.key);
update_source_layers_cache(event.key, layer);
} else {
layer = read_source_layers_cache(event.key);
}
return keymap_key_to_keycode(layer, event.key);
} else
#endif
return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key);
}
/* Main keycode processing function. Hands off handling to other functions,
* then processes internal Quantum keycodes, then processes ACTIONs.
*/
bool process_record_quantum(keyrecord_t *record) {
uint16_t keycode = get_record_keycode(record);
// This is how you use actions here
// if (keycode == KC_LEAD) {
// action_t action;
// action.code = ACTION_DEFAULT_LAYER_SET(0);
// process_action(record, action);
// return false;
// }
#ifdef VELOCIKEY_ENABLE
if (veloc
|