Merge branch 'master' into to_push
This commit is contained in:
commit
2366ebfbbd
743 changed files with 63747 additions and 7067 deletions
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2015 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/>.
|
||||
*/
|
||||
|
||||
// Simple analog to digitial conversion
|
||||
|
||||
#include <avr/io.h>
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2015 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _analog_h_included__
|
||||
#define _analog_h_included__
|
||||
|
||||
|
|
195
quantum/api.c
Normal file
195
quantum/api.c
Normal file
|
@ -0,0 +1,195 @@
|
|||
/* Copyright 2016 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 "api.h"
|
||||
#include "quantum.h"
|
||||
|
||||
void dword_to_bytes(uint32_t dword, uint8_t * bytes) {
|
||||
bytes[0] = (dword >> 24) & 0xFF;
|
||||
bytes[1] = (dword >> 16) & 0xFF;
|
||||
bytes[2] = (dword >> 8) & 0xFF;
|
||||
bytes[3] = (dword >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
uint32_t bytes_to_dword(uint8_t * bytes, uint8_t index) {
|
||||
return ((uint32_t)bytes[index + 0] << 24) | ((uint32_t)bytes[index + 1] << 16) | ((uint32_t)bytes[index + 2] << 8) | (uint32_t)bytes[index + 3];
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
bool process_api_quantum(uint8_t length, uint8_t * data) {
|
||||
return process_api_keyboard(length, data);
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
bool process_api_keyboard(uint8_t length, uint8_t * data) {
|
||||
return process_api_user(length, data);
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
bool process_api_user(uint8_t length, uint8_t * data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void process_api(uint16_t length, uint8_t * data) {
|
||||
// SEND_STRING("\nRX: ");
|
||||
// for (uint8_t i = 0; i < length; i++) {
|
||||
// send_byte(data[i]);
|
||||
// SEND_STRING(" ");
|
||||
// }
|
||||
if (!process_api_quantum(length, data))
|
||||
return;
|
||||
|
||||
switch (data[0]) {
|
||||
case MT_SET_DATA:
|
||||
switch (data[1]) {
|
||||
case DT_DEFAULT_LAYER: {
|
||||
eeconfig_update_default_layer(data[2]);
|
||||
default_layer_set((uint32_t)(data[2]));
|
||||
break;
|
||||
}
|
||||
case DT_KEYMAP_OPTIONS: {
|
||||
eeconfig_update_keymap(data[2]);
|
||||
break;
|
||||
}
|
||||
case DT_RGBLIGHT: {
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
uint32_t rgblight = bytes_to_dword(data, 2);
|
||||
rgblight_update_dword(rgblight);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
case MT_GET_DATA:
|
||||
switch (data[1]) {
|
||||
case DT_HANDSHAKE: {
|
||||
MT_GET_DATA_ACK(DT_HANDSHAKE, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case DT_DEBUG: {
|
||||
uint8_t debug_bytes[1] = { eeprom_read_byte(EECONFIG_DEBUG) };
|
||||
MT_GET_DATA_ACK(DT_DEBUG, debug_bytes, 1);
|
||||
break;
|
||||
}
|
||||
case DT_DEFAULT_LAYER: {
|
||||
uint8_t default_bytes[1] = { eeprom_read_byte(EECONFIG_DEFAULT_LAYER) };
|
||||
MT_GET_DATA_ACK(DT_DEFAULT_LAYER, default_bytes, 1);
|
||||
break;
|
||||
}
|
||||
case DT_CURRENT_LAYER: {
|
||||
uint8_t layer_state_bytes[4];
|
||||
dword_to_bytes(layer_state, layer_state_bytes);
|
||||
MT_GET_DATA_ACK(DT_CURRENT_LAYER, layer_state_bytes, 4);
|
||||
break;
|
||||
}
|
||||
case DT_AUDIO: {
|
||||
#ifdef AUDIO_ENABLE
|
||||
uint8_t audio_bytes[1] = { eeprom_read_byte(EECONFIG_AUDIO) };
|
||||
MT_GET_DATA_ACK(DT_AUDIO, audio_bytes, 1);
|
||||
#else
|
||||
MT_GET_DATA_ACK(DT_AUDIO, NULL, 0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case DT_BACKLIGHT: {
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
uint8_t backlight_bytes[1] = { eeprom_read_byte(EECONFIG_BACKLIGHT) };
|
||||
MT_GET_DATA_ACK(DT_BACKLIGHT, backlight_bytes, 1);
|
||||
#else
|
||||
MT_GET_DATA_ACK(DT_BACKLIGHT, NULL, 0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case DT_RGBLIGHT: {
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
uint8_t rgblight_bytes[4];
|
||||
dword_to_bytes(eeconfig_read_rgblight(), rgblight_bytes);
|
||||
MT_GET_DATA_ACK(DT_RGBLIGHT, rgblight_bytes, 4);
|
||||
#else
|
||||
MT_GET_DATA_ACK(DT_RGBLIGHT, NULL, 0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case DT_KEYMAP_OPTIONS: {
|
||||
uint8_t keymap_bytes[1] = { eeconfig_read_keymap() };
|
||||
MT_GET_DATA_ACK(DT_KEYMAP_OPTIONS, keymap_bytes, 1);
|
||||
break;
|
||||
}
|
||||
case DT_KEYMAP_SIZE: {
|
||||
uint8_t keymap_size[2] = {MATRIX_ROWS, MATRIX_COLS};
|
||||
MT_GET_DATA_ACK(DT_KEYMAP_SIZE, keymap_size, 2);
|
||||
break;
|
||||
}
|
||||
// This may be too much
|
||||
// case DT_KEYMAP: {
|
||||
// uint8_t keymap_data[MATRIX_ROWS * MATRIX_COLS * 4 + 3];
|
||||
// keymap_data[0] = data[2];
|
||||
// keymap_data[1] = MATRIX_ROWS;
|
||||
// keymap_data[2] = MATRIX_COLS;
|
||||
// for (int i = 0; i < MATRIX_ROWS; i++) {
|
||||
// for (int j = 0; j < MATRIX_COLS; j++) {
|
||||
// keymap_data[3 + (i*MATRIX_COLS*2) + (j*2)] = pgm_read_word(&keymaps[data[2]][i][j]) >> 8;
|
||||
// keymap_data[3 + (i*MATRIX_COLS*2) + (j*2) + 1] = pgm_read_word(&keymaps[data[2]][i][j]) & 0xFF;
|
||||
// }
|
||||
// }
|
||||
// MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, MATRIX_ROWS * MATRIX_COLS * 4 + 3);
|
||||
// // uint8_t keymap_data[5];
|
||||
// // keymap_data[0] = data[2];
|
||||
// // keymap_data[1] = data[3];
|
||||
// // keymap_data[2] = data[4];
|
||||
// // keymap_data[3] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) >> 8;
|
||||
// // keymap_data[4] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) & 0xFF;
|
||||
|
||||
// // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, 5);
|
||||
// break;
|
||||
// }
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MT_SET_DATA_ACK:
|
||||
case MT_GET_DATA_ACK:
|
||||
break;
|
||||
case MT_SEND_DATA:
|
||||
break;
|
||||
case MT_SEND_DATA_ACK:
|
||||
break;
|
||||
case MT_EXE_ACTION:
|
||||
break;
|
||||
case MT_EXE_ACTION_ACK:
|
||||
break;
|
||||
case MT_TYPE_ERROR:
|
||||
break;
|
||||
default: ; // command not recognised
|
||||
SEND_BYTES(MT_TYPE_ERROR, DT_NONE, data, length);
|
||||
break;
|
||||
|
||||
// #ifdef RGBLIGHT_ENABLE
|
||||
// case 0x27: ; // RGB LED functions
|
||||
// switch (*data++) {
|
||||
// case 0x00: ; // Update HSV
|
||||
// rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]);
|
||||
// break;
|
||||
// case 0x01: ; // Update RGB
|
||||
// break;
|
||||
// case 0x02: ; // Update mode
|
||||
// rgblight_mode(data[0]);
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// #endif
|
||||
}
|
||||
|
||||
}
|
75
quantum/api.h
Normal file
75
quantum/api.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _API_H_
|
||||
#define _API_H_
|
||||
|
||||
#include "lufa.h"
|
||||
|
||||
enum MESSAGE_TYPE {
|
||||
MT_GET_DATA = 0x10, // Get data from keyboard
|
||||
MT_GET_DATA_ACK = 0x11, // returned data to process (ACK)
|
||||
MT_SET_DATA = 0x20, // Set data on keyboard
|
||||
MT_SET_DATA_ACK = 0x21, // returned data to confirm (ACK)
|
||||
MT_SEND_DATA = 0x30, // Sending data/action from keyboard
|
||||
MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK)
|
||||
MT_EXE_ACTION = 0x40, // executing actions on keyboard
|
||||
MT_EXE_ACTION_ACK =0x41, // return confirmation/value (ACK)
|
||||
MT_TYPE_ERROR = 0x80 // type not recofgnised (ACK)
|
||||
};
|
||||
|
||||
enum DATA_TYPE {
|
||||
DT_NONE = 0x00,
|
||||
DT_HANDSHAKE,
|
||||
DT_DEFAULT_LAYER,
|
||||
DT_CURRENT_LAYER,
|
||||
DT_KEYMAP_OPTIONS,
|
||||
DT_BACKLIGHT,
|
||||
DT_RGBLIGHT,
|
||||
DT_UNICODE,
|
||||
DT_DEBUG,
|
||||
DT_AUDIO,
|
||||
DT_QUANTUM_ACTION,
|
||||
DT_KEYBOARD_ACTION,
|
||||
DT_USER_ACTION,
|
||||
DT_KEYMAP_SIZE,
|
||||
DT_KEYMAP
|
||||
};
|
||||
|
||||
void dword_to_bytes(uint32_t dword, uint8_t * bytes);
|
||||
uint32_t bytes_to_dword(uint8_t * bytes, uint8_t index);
|
||||
|
||||
#define MT_GET_DATA(data_type, data, length) SEND_BYTES(MT_GET_DATA, data_type, data, length)
|
||||
#define MT_GET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_GET_DATA_ACK, data_type, data, length)
|
||||
#define MT_SET_DATA(data_type, data, length) SEND_BYTES(MT_SET_DATA, data_type, data, length)
|
||||
#define MT_SET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SET_DATA_ACK, data_type, data, length)
|
||||
#define MT_SEND_DATA(data_type, data, length) SEND_BYTES(MT_SEND_DATA, data_type, data, length)
|
||||
#define MT_SEND_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SEND_DATA_ACK, data_type, data, length)
|
||||
#define MT_EXE_ACTION(data_type, data, length) SEND_BYTES(MT_EXE_ACTION, data_type, data, length)
|
||||
#define MT_EXE_ACTION_ACK(data_type, data, length) SEND_BYTES(MT_EXE_ACTION_ACK, data_type, data, length)
|
||||
|
||||
void process_api(uint16_t length, uint8_t * data);
|
||||
|
||||
__attribute__ ((weak))
|
||||
bool process_api_quantum(uint8_t length, uint8_t * data);
|
||||
|
||||
__attribute__ ((weak))
|
||||
bool process_api_keyboard(uint8_t length, uint8_t * data);
|
||||
|
||||
__attribute__ ((weak))
|
||||
bool process_api_user(uint8_t length, uint8_t * data);
|
||||
|
||||
#endif
|
72
quantum/api/api_sysex.c
Normal file
72
quantum/api/api_sysex.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Copyright 2016 Jack Humbert, Fred Sundvik
|
||||
*
|
||||
* 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 "api_sysex.h"
|
||||
#include "sysex_tools.h"
|
||||
#include "print.h"
|
||||
|
||||
void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length) {
|
||||
// SEND_STRING("\nTX: ");
|
||||
// for (uint8_t i = 0; i < length; i++) {
|
||||
// send_byte(bytes[i]);
|
||||
// SEND_STRING(" ");
|
||||
// }
|
||||
if (length > API_SYSEX_MAX_SIZE) {
|
||||
xprintf("Sysex msg too big %d %d %d", message_type, data_type, length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// The buffer size required is calculated as the following
|
||||
// API_SYSEX_MAX_SIZE is the maximum length
|
||||
// In addition to that we have a two byte message header consisting of the message_type and data_type
|
||||
// This has to be encoded with an additional overhead of one byte for every starting 7 bytes
|
||||
// We just add one extra byte in case it's not divisible by 7
|
||||
// Then we have an unencoded header consisting of 4 bytes
|
||||
// Plus a one byte terminator
|
||||
const unsigned message_header = 2;
|
||||
const unsigned unencoded_message = API_SYSEX_MAX_SIZE + message_header;
|
||||
const unsigned encoding_overhead = unencoded_message / 7 + 1;
|
||||
const unsigned encoded_size = unencoded_message + encoding_overhead;
|
||||
const unsigned unencoded_header = 4;
|
||||
const unsigned terminator = 1;
|
||||
const unsigned buffer_size = encoded_size + unencoded_header + terminator;
|
||||
uint8_t buffer[encoded_size + unencoded_header + terminator];
|
||||
// The unencoded header
|
||||
buffer[0] = 0xF0;
|
||||
buffer[1] = 0x00;
|
||||
buffer[2] = 0x00;
|
||||
buffer[3] = 0x00;
|
||||
|
||||
// We copy the message to the end of the array, this way we can do an inplace encoding, using the same
|
||||
// buffer for both input and output
|
||||
const unsigned message_size = length + message_header;
|
||||
uint8_t* unencoded_start = buffer + buffer_size - message_size;
|
||||
uint8_t* ptr = unencoded_start;
|
||||
*(ptr++) = message_type;
|
||||
*(ptr++) = data_type;
|
||||
memcpy(ptr, bytes, length);
|
||||
|
||||
unsigned encoded_length = sysex_encode(buffer + unencoded_header, unencoded_start, message_size);
|
||||
unsigned final_size = unencoded_header + encoded_length + terminator;
|
||||
buffer[final_size - 1] = 0xF7;
|
||||
midi_send_array(&midi_device, final_size, buffer);
|
||||
|
||||
// SEND_STRING("\nTD: ");
|
||||
// for (uint8_t i = 0; i < encoded_length + 5; i++) {
|
||||
// send_byte(buffer[i]);
|
||||
// SEND_STRING(" ");
|
||||
// }
|
||||
}
|
26
quantum/api/api_sysex.h
Normal file
26
quantum/api/api_sysex.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _API_SYSEX_H_
|
||||
#define _API_SYSEX_H_
|
||||
|
||||
#include "api.h"
|
||||
|
||||
void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length);
|
||||
|
||||
#define SEND_BYTES(mt, dt, b, l) send_bytes_sysex(mt, dt, b, l)
|
||||
|
||||
#endif
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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 <stdio.h>
|
||||
#include <string.h>
|
||||
//#include <math.h>
|
||||
|
@ -77,6 +92,7 @@ static bool audio_initialized = false;
|
|||
audio_config_t audio_config;
|
||||
|
||||
uint16_t envelope_index = 0;
|
||||
bool glissando = true;
|
||||
|
||||
void audio_init()
|
||||
{
|
||||
|
@ -88,15 +104,15 @@ void audio_init()
|
|||
}
|
||||
audio_config.raw = eeconfig_read_audio();
|
||||
|
||||
// Set port PC6 (OC3A and /OC4A) as output
|
||||
// Set port PC6 (OC3A and /OC4A) as output
|
||||
DDRC |= _BV(PORTC6);
|
||||
|
||||
DISABLE_AUDIO_COUNTER_3_ISR;
|
||||
|
||||
// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
|
||||
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
|
||||
// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
|
||||
// Clock Select (CS3n) = 0b010 = Clock / 8
|
||||
// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
|
||||
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
|
||||
// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
|
||||
// Clock Select (CS3n) = 0b010 = Clock / 8
|
||||
TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
|
||||
TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
|
||||
|
||||
|
@ -105,6 +121,8 @@ void audio_init()
|
|||
|
||||
void stop_all_notes()
|
||||
{
|
||||
dprintf("audio stop all notes");
|
||||
|
||||
if (!audio_initialized) {
|
||||
audio_init();
|
||||
}
|
||||
|
@ -127,6 +145,8 @@ void stop_all_notes()
|
|||
|
||||
void stop_note(float freq)
|
||||
{
|
||||
dprintf("audio stop note freq=%d", (int)freq);
|
||||
|
||||
if (playing_note) {
|
||||
if (!audio_initialized) {
|
||||
audio_init();
|
||||
|
@ -182,155 +202,161 @@ float vibrato(float average_freq) {
|
|||
|
||||
ISR(TIMER3_COMPA_vect)
|
||||
{
|
||||
float freq;
|
||||
float freq;
|
||||
|
||||
if (playing_note) {
|
||||
if (voices > 0) {
|
||||
if (polyphony_rate > 0) {
|
||||
if (voices > 1) {
|
||||
voice_place %= voices;
|
||||
if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
|
||||
voice_place = (voice_place + 1) % voices;
|
||||
place = 0.0;
|
||||
}
|
||||
}
|
||||
if (playing_note) {
|
||||
if (voices > 0) {
|
||||
if (polyphony_rate > 0) {
|
||||
if (voices > 1) {
|
||||
voice_place %= voices;
|
||||
if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
|
||||
voice_place = (voice_place + 1) % voices;
|
||||
place = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VIBRATO_ENABLE
|
||||
if (vibrato_strength > 0) {
|
||||
freq = vibrato(frequencies[voice_place]);
|
||||
} else {
|
||||
freq = frequencies[voice_place];
|
||||
}
|
||||
#else
|
||||
freq = frequencies[voice_place];
|
||||
#endif
|
||||
} else {
|
||||
if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
|
||||
frequency = frequency * pow(2, 440/frequency/12/2);
|
||||
} else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
|
||||
frequency = frequency * pow(2, -440/frequency/12/2);
|
||||
} else {
|
||||
frequency = frequencies[voices - 1];
|
||||
}
|
||||
#ifdef VIBRATO_ENABLE
|
||||
if (vibrato_strength > 0) {
|
||||
freq = vibrato(frequencies[voice_place]);
|
||||
} else {
|
||||
freq = frequencies[voice_place];
|
||||
}
|
||||
#else
|
||||
freq = frequencies[voice_place];
|
||||
#endif
|
||||
} else {
|
||||
if (glissando) {
|
||||
if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
|
||||
frequency = frequency * pow(2, 440/frequency/12/2);
|
||||
} else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
|
||||
frequency = frequency * pow(2, -440/frequency/12/2);
|
||||
} else {
|
||||
frequency = frequencies[voices - 1];
|
||||
}
|
||||
} else {
|
||||
frequency = frequencies[voices - 1];
|
||||
}
|
||||
|
||||
#ifdef VIBRATO_ENABLE
|
||||
if (vibrato_strength > 0) {
|
||||
freq = vibrato(frequency);
|
||||
} else {
|
||||
freq = frequency;
|
||||
}
|
||||
#else
|
||||
freq = frequency;
|
||||
#endif
|
||||
}
|
||||
#ifdef VIBRATO_ENABLE
|
||||
if (vibrato_strength > 0) {
|
||||
freq = vibrato(frequency);
|
||||
} else {
|
||||
freq = frequency;
|
||||
}
|
||||
#else
|
||||
freq = frequency;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (envelope_index < 65535) {
|
||||
envelope_index++;
|
||||
}
|
||||
if (envelope_index < 65535) {
|
||||
envelope_index++;
|
||||
}
|
||||
|
||||
freq = voice_envelope(freq);
|
||||
freq = voice_envelope(freq);
|
||||
|
||||
if (freq < 30.517578125) {
|
||||
freq = 30.52;
|
||||
}
|
||||
if (freq < 30.517578125) {
|
||||
freq = 30.52;
|
||||
}
|
||||
|
||||
TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
|
||||
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
|
||||
}
|
||||
}
|
||||
TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
|
||||
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
|
||||
}
|
||||
}
|
||||
|
||||
if (playing_notes) {
|
||||
if (note_frequency > 0) {
|
||||
#ifdef VIBRATO_ENABLE
|
||||
if (vibrato_strength > 0) {
|
||||
freq = vibrato(note_frequency);
|
||||
} else {
|
||||
freq = note_frequency;
|
||||
}
|
||||
#else
|
||||
freq = note_frequency;
|
||||
#endif
|
||||
if (playing_notes) {
|
||||
if (note_frequency > 0) {
|
||||
#ifdef VIBRATO_ENABLE
|
||||
if (vibrato_strength > 0) {
|
||||
freq = vibrato(note_frequency);
|
||||
} else {
|
||||
freq = note_frequency;
|
||||
}
|
||||
#else
|
||||
freq = note_frequency;
|
||||
#endif
|
||||
|
||||
if (envelope_index < 65535) {
|
||||
envelope_index++;
|
||||
}
|
||||
freq = voice_envelope(freq);
|
||||
if (envelope_index < 65535) {
|
||||
envelope_index++;
|
||||
}
|
||||
freq = voice_envelope(freq);
|
||||
|
||||
TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
|
||||
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
|
||||
} else {
|
||||
TIMER_3_PERIOD = 0;
|
||||
TIMER_3_DUTY_CYCLE = 0;
|
||||
}
|
||||
TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
|
||||
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
|
||||
} else {
|
||||
TIMER_3_PERIOD = 0;
|
||||
TIMER_3_DUTY_CYCLE = 0;
|
||||
}
|
||||
|
||||
note_position++;
|
||||
bool end_of_note = false;
|
||||
if (TIMER_3_PERIOD > 0) {
|
||||
end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF));
|
||||
} else {
|
||||
end_of_note = (note_position >= (note_length * 0x7FF));
|
||||
}
|
||||
note_position++;
|
||||
bool end_of_note = false;
|
||||
if (TIMER_3_PERIOD > 0) {
|
||||
end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF));
|
||||
} else {
|
||||
end_of_note = (note_position >= (note_length * 0x7FF));
|
||||
}
|
||||
|
||||
if (end_of_note) {
|
||||
current_note++;
|
||||
if (current_note >= notes_count) {
|
||||
if (notes_repeat) {
|
||||
current_note = 0;
|
||||
} else {
|
||||
DISABLE_AUDIO_COUNTER_3_ISR;
|
||||
DISABLE_AUDIO_COUNTER_3_OUTPUT;
|
||||
playing_notes = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!note_resting && (notes_rest > 0)) {
|
||||
note_resting = true;
|
||||
note_frequency = 0;
|
||||
note_length = notes_rest;
|
||||
current_note--;
|
||||
} else {
|
||||
note_resting = false;
|
||||
envelope_index = 0;
|
||||
note_frequency = (*notes_pointer)[current_note][0];
|
||||
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
|
||||
}
|
||||
if (end_of_note) {
|
||||
current_note++;
|
||||
if (current_note >= notes_count) {
|
||||
if (notes_repeat) {
|
||||
current_note = 0;
|
||||
} else {
|
||||
DISABLE_AUDIO_COUNTER_3_ISR;
|
||||
DISABLE_AUDIO_COUNTER_3_OUTPUT;
|
||||
playing_notes = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!note_resting && (notes_rest > 0)) {
|
||||
note_resting = true;
|
||||
note_frequency = 0;
|
||||
note_length = notes_rest;
|
||||
current_note--;
|
||||
} else {
|
||||
note_resting = false;
|
||||
envelope_index = 0;
|
||||
note_frequency = (*notes_pointer)[current_note][0];
|
||||
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
|
||||
}
|
||||
|
||||
note_position = 0;
|
||||
}
|
||||
}
|
||||
note_position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!audio_config.enable) {
|
||||
playing_notes = false;
|
||||
playing_note = false;
|
||||
}
|
||||
if (!audio_config.enable) {
|
||||
playing_notes = false;
|
||||
playing_note = false;
|
||||
}
|
||||
}
|
||||
|
||||
void play_note(float freq, int vol) {
|
||||
|
||||
dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
|
||||
|
||||
if (!audio_initialized) {
|
||||
audio_init();
|
||||
}
|
||||
|
||||
if (audio_config.enable && voices < 8) {
|
||||
DISABLE_AUDIO_COUNTER_3_ISR;
|
||||
if (audio_config.enable && voices < 8) {
|
||||
DISABLE_AUDIO_COUNTER_3_ISR;
|
||||
|
||||
// Cancel notes if notes are playing
|
||||
if (playing_notes)
|
||||
stop_all_notes();
|
||||
// Cancel notes if notes are playing
|
||||
if (playing_notes)
|
||||
stop_all_notes();
|
||||
|
||||
playing_note = true;
|
||||
playing_note = true;
|
||||
|
||||
envelope_index = 0;
|
||||
envelope_index = 0;
|
||||
|
||||
if (freq > 0) {
|
||||
frequencies[voices] = freq;
|
||||
volumes[voices] = vol;
|
||||
voices++;
|
||||
}
|
||||
if (freq > 0) {
|
||||
frequencies[voices] = freq;
|
||||
volumes[voices] = vol;
|
||||
voices++;
|
||||
}
|
||||
|
||||
ENABLE_AUDIO_COUNTER_3_ISR;
|
||||
ENABLE_AUDIO_COUNTER_3_OUTPUT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -341,37 +367,37 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
|
|||
audio_init();
|
||||
}
|
||||
|
||||
if (audio_config.enable) {
|
||||
if (audio_config.enable) {
|
||||
|
||||
DISABLE_AUDIO_COUNTER_3_ISR;
|
||||
DISABLE_AUDIO_COUNTER_3_ISR;
|
||||
|
||||
// Cancel note if a note is playing
|
||||
if (playing_note)
|
||||
stop_all_notes();
|
||||
// Cancel note if a note is playing
|
||||
if (playing_note)
|
||||
stop_all_notes();
|
||||
|
||||
playing_notes = true;
|
||||
playing_notes = true;
|
||||
|
||||
notes_pointer = np;
|
||||
notes_count = n_count;
|
||||
notes_repeat = n_repeat;
|
||||
notes_rest = n_rest;
|
||||
notes_pointer = np;
|
||||
notes_count = n_count;
|
||||
notes_repeat = n_repeat;
|
||||
notes_rest = n_rest;
|
||||
|
||||
place = 0;
|
||||
current_note = 0;
|
||||
place = 0;
|
||||
current_note = 0;
|
||||
|
||||
note_frequency = (*notes_pointer)[current_note][0];
|
||||
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
|
||||
note_position = 0;
|
||||
note_position = 0;
|
||||
|
||||
|
||||
ENABLE_AUDIO_COUNTER_3_ISR;
|
||||
ENABLE_AUDIO_COUNTER_3_OUTPUT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool is_playing_notes(void) {
|
||||
return playing_notes;
|
||||
return playing_notes;
|
||||
}
|
||||
|
||||
bool is_audio_on(void) {
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
|
@ -88,4 +103,4 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
|
|||
|
||||
bool is_playing_notes(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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 <stdio.h>
|
||||
#include <string.h>
|
||||
//#include <math.h>
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 IBNobody
|
||||
*
|
||||
* 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 <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 IBNobody
|
||||
*
|
||||
* 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 <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
@ -12,4 +28,4 @@
|
|||
extern const float vibrato_lut[VIBRATO_LUT_LENGTH];
|
||||
extern const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH];
|
||||
|
||||
#endif /* LUTS_H */
|
||||
#endif /* LUTS_H */
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef MUSICAL_NOTES_H
|
||||
#define MUSICAL_NOTES_H
|
||||
|
||||
|
@ -214,4 +230,4 @@
|
|||
#define NOTE_BF8 NOTE_AS8
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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 "musical_notes.h"
|
||||
|
||||
#ifndef SONG_LIST_H
|
||||
|
@ -134,4 +149,31 @@
|
|||
E__NOTE(_E6), \
|
||||
S__NOTE(_B5),
|
||||
|
||||
#define COIN_SOUND \
|
||||
E__NOTE(_A5 ), \
|
||||
HD_NOTE(_E6 ),
|
||||
|
||||
#define ONE_UP_SOUND \
|
||||
Q__NOTE(_E6 ), \
|
||||
Q__NOTE(_G6 ), \
|
||||
Q__NOTE(_E7 ), \
|
||||
Q__NOTE(_C7 ), \
|
||||
Q__NOTE(_D7 ), \
|
||||
Q__NOTE(_G7 ),
|
||||
|
||||
#define SONIC_RING \
|
||||
E__NOTE(_E6), \
|
||||
E__NOTE(_G6), \
|
||||
HD_NOTE(_C7),
|
||||
|
||||
#define ZELDA_PUZZLE \
|
||||
Q__NOTE(_G5), \
|
||||
Q__NOTE(_FS5), \
|
||||
Q__NOTE(_DS5), \
|
||||
Q__NOTE(_A4), \
|
||||
Q__NOTE(_GS4), \
|
||||
Q__NOTE(_E5), \
|
||||
Q__NOTE(_GS5), \
|
||||
HD_NOTE(_C6),
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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 "voices.h"
|
||||
#include "audio.h"
|
||||
#include "stdlib.h"
|
||||
|
@ -6,6 +21,7 @@
|
|||
extern uint16_t envelope_index;
|
||||
extern float note_timbre;
|
||||
extern float polyphony_rate;
|
||||
extern bool glissando;
|
||||
|
||||
voice_type voice = default_voice;
|
||||
|
||||
|
@ -18,20 +34,132 @@ void voice_iterate() {
|
|||
}
|
||||
|
||||
void voice_deiterate() {
|
||||
voice = (voice - 1) % number_of_voices;
|
||||
voice = (voice - 1 + number_of_voices) % number_of_voices;
|
||||
}
|
||||
|
||||
float voice_envelope(float frequency) {
|
||||
// envelope_index ranges from 0 to 0xFFFF, which is preserved at 880.0 Hz
|
||||
__attribute__ ((unused))
|
||||
uint16_t compensated_index = (uint16_t)((float)envelope_index * (880.0 / frequency));
|
||||
|
||||
switch (voice) {
|
||||
case default_voice:
|
||||
glissando = true;
|
||||
note_timbre = TIMBRE_50;
|
||||
polyphony_rate = 0;
|
||||
break;
|
||||
|
||||
#ifdef AUDIO_VOICES
|
||||
|
||||
case something:
|
||||
glissando = false;
|
||||
polyphony_rate = 0;
|
||||
switch (compensated_index) {
|
||||
case 0 ... 9:
|
||||
note_timbre = TIMBRE_12;
|
||||
break;
|
||||
|
||||
case 10 ... 19:
|
||||
note_timbre = TIMBRE_25;
|
||||
break;
|
||||
|
||||
case 20 ... 200:
|
||||
note_timbre = .125 + .125;
|
||||
break;
|
||||
|
||||
default:
|
||||
note_timbre = .125;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case drums:
|
||||
glissando = false;
|
||||
polyphony_rate = 0;
|
||||
// switch (compensated_index) {
|
||||
// case 0 ... 10:
|
||||
// note_timbre = 0.5;
|
||||
// break;
|
||||
// case 11 ... 20:
|
||||
// note_timbre = 0.5 * (21 - compensated_index) / 10;
|
||||
// break;
|
||||
// default:
|
||||
// note_timbre = 0;
|
||||
// break;
|
||||
// }
|
||||
// frequency = (rand() % (int)(frequency * 1.2 - frequency)) + (frequency * 0.8);
|
||||
|
||||
if (frequency < 80.0) {
|
||||
|
||||
} else if (frequency < 160.0) {
|
||||
|
||||
// Bass drum: 60 - 100 Hz
|
||||
frequency = (rand() % (int)(40)) + 60;
|
||||
switch (envelope_index) {
|
||||
case 0 ... 10:
|
||||
note_timbre = 0.5;
|
||||
break;
|
||||
case 11 ... 20:
|
||||
note_timbre = 0.5 * (21 - envelope_index) / 10;
|
||||
break;
|
||||
default:
|
||||
note_timbre = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (frequency < 320.0) {
|
||||
|
||||
|
||||
// Snare drum: 1 - 2 KHz
|
||||
frequency = (rand() % (int)(1000)) + 1000;
|
||||
switch (envelope_index) {
|
||||
case 0 ... 5:
|
||||
note_timbre = 0.5;
|
||||
break;
|
||||
case 6 ... 20:
|
||||
note_timbre = 0.5 * (21 - envelope_index) / 15;
|
||||
break;
|
||||
default:
|
||||
note_timbre = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (frequency < 640.0) {
|
||||
|
||||
// Closed Hi-hat: 3 - 5 KHz
|
||||
frequency = (rand() % (int)(2000)) + 3000;
|
||||
switch (envelope_index) {
|
||||
case 0 ... 15:
|
||||
note_timbre = 0.5;
|
||||
break;
|
||||
case 16 ... 20:
|
||||
note_timbre = 0.5 * (21 - envelope_index) / 5;
|
||||
break;
|
||||
default:
|
||||
note_timbre = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (frequency < 1280.0) {
|
||||
|
||||
// Open Hi-hat: 3 - 5 KHz
|
||||
frequency = (rand() % (int)(2000)) + 3000;
|
||||
switch (envelope_index) {
|
||||
case 0 ... 35:
|
||||
note_timbre = 0.5;
|
||||
break;
|
||||
case 36 ... 50:
|
||||
note_timbre = 0.5 * (51 - envelope_index) / 15;
|
||||
break;
|
||||
default:
|
||||
note_timbre = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case butts_fader:
|
||||
glissando = true;
|
||||
polyphony_rate = 0;
|
||||
switch (compensated_index) {
|
||||
case 0 ... 9:
|
||||
|
@ -79,6 +207,7 @@ float voice_envelope(float frequency) {
|
|||
|
||||
case duty_osc:
|
||||
// This slows the loop down a substantial amount, so higher notes may freeze
|
||||
glissando = true;
|
||||
polyphony_rate = 0;
|
||||
switch (compensated_index) {
|
||||
default:
|
||||
|
@ -93,6 +222,7 @@ float voice_envelope(float frequency) {
|
|||
break;
|
||||
|
||||
case duty_octave_down:
|
||||
glissando = true;
|
||||
polyphony_rate = 0;
|
||||
note_timbre = (envelope_index % 2) * .125 + .375 * 2;
|
||||
if ((envelope_index % 4) == 0)
|
||||
|
@ -101,6 +231,7 @@ float voice_envelope(float frequency) {
|
|||
note_timbre = 0;
|
||||
break;
|
||||
case delayed_vibrato:
|
||||
glissando = true;
|
||||
polyphony_rate = 0;
|
||||
note_timbre = TIMBRE_50;
|
||||
#define VOICE_VIBRATO_DELAY 150
|
||||
|
@ -155,11 +286,11 @@ float voice_envelope(float frequency) {
|
|||
// note_timbre = 0.25;
|
||||
// break;
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
|
@ -11,6 +26,9 @@ float voice_envelope(float frequency);
|
|||
|
||||
typedef enum {
|
||||
default_voice,
|
||||
#ifdef AUDIO_VOICES
|
||||
something,
|
||||
drums,
|
||||
butts_fader,
|
||||
octave_crunch,
|
||||
duty_osc,
|
||||
|
@ -21,6 +39,7 @@ typedef enum {
|
|||
// duty_fourth_down,
|
||||
// duty_third_down,
|
||||
// duty_fifth_third_down,
|
||||
#endif
|
||||
number_of_voices // important that this is last
|
||||
} voice_type;
|
||||
|
||||
|
@ -28,4 +47,4 @@ void set_voice(voice_type v);
|
|||
void voice_iterate(void);
|
||||
void voice_deiterate(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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 <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
@ -262,4 +278,4 @@ const uint8_t sinewave[] PROGMEM= //2048 values
|
|||
0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,
|
||||
0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,
|
||||
0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,59 +1,78 @@
|
|||
/* Copyright 2015-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/>.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DEFINITIONS_H
|
||||
#define CONFIG_DEFINITIONS_H
|
||||
|
||||
/* diode directions */
|
||||
#define COL2ROW 0
|
||||
#define ROW2COL 1
|
||||
/* I/O pins */
|
||||
#define B0 0x30
|
||||
#define B1 0x31
|
||||
#define B2 0x32
|
||||
#define B3 0x33
|
||||
#define B4 0x34
|
||||
#define B5 0x35
|
||||
#define B6 0x36
|
||||
#define B7 0x37
|
||||
#define C0 0x60
|
||||
#define C1 0x61
|
||||
#define C2 0x62
|
||||
#define C3 0x63
|
||||
#define C4 0x64
|
||||
#define C5 0x65
|
||||
#define C6 0x66
|
||||
#define C7 0x67
|
||||
#define D0 0x90
|
||||
#define D1 0x91
|
||||
#define D2 0x92
|
||||
#define D3 0x93
|
||||
#define D4 0x94
|
||||
#define D5 0x95
|
||||
#define D6 0x96
|
||||
#define D7 0x97
|
||||
#define E0 0xC0
|
||||
#define E1 0xC1
|
||||
#define E2 0xC2
|
||||
#define E3 0xC3
|
||||
#define E4 0xC4
|
||||
#define E5 0xC5
|
||||
#define E6 0xC6
|
||||
#define E7 0xC7
|
||||
#define F0 0xF0
|
||||
#define F1 0xF1
|
||||
#define F2 0xF2
|
||||
#define F3 0xF3
|
||||
#define F4 0xF4
|
||||
#define F5 0xF5
|
||||
#define F6 0xF6
|
||||
#define F7 0xF7
|
||||
#define A0 0x00
|
||||
#define A1 0x01
|
||||
#define A2 0x02
|
||||
#define A3 0x03
|
||||
#define A4 0x04
|
||||
#define A5 0x05
|
||||
#define A6 0x06
|
||||
#define A7 0x07
|
||||
#define COL2ROW 0
|
||||
#define ROW2COL 1
|
||||
#define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */
|
||||
|
||||
/* I/O pins */
|
||||
#ifndef F0
|
||||
#define B0 0x30
|
||||
#define B1 0x31
|
||||
#define B2 0x32
|
||||
#define B3 0x33
|
||||
#define B4 0x34
|
||||
#define B5 0x35
|
||||
#define B6 0x36
|
||||
#define B7 0x37
|
||||
#define C0 0x60
|
||||
#define C1 0x61
|
||||
#define C2 0x62
|
||||
#define C3 0x63
|
||||
#define C4 0x64
|
||||
#define C5 0x65
|
||||
#define C6 0x66
|
||||
#define C7 0x67
|
||||
#define D0 0x90
|
||||
#define D1 0x91
|
||||
#define D2 0x92
|
||||
#define D3 0x93
|
||||
#define D4 0x94
|
||||
#define D5 0x95
|
||||
#define D6 0x96
|
||||
#define D7 0x97
|
||||
#define E0 0xC0
|
||||
#define E1 0xC1
|
||||
#define E2 0xC2
|
||||
#define E3 0xC3
|
||||
#define E4 0xC4
|
||||
#define E5 0xC5
|
||||
#define E6 0xC6
|
||||
#define E7 0xC7
|
||||
#define F0 0xF0
|
||||
#define F1 0xF1
|
||||
#define F2 0xF2
|
||||
#define F3 0xF3
|
||||
#define F4 0xF4
|
||||
#define F5 0xF5
|
||||
#define F6 0xF6
|
||||
#define F7 0xF7
|
||||
#define A0 0x00
|
||||
#define A1 0x01
|
||||
#define A2 0x02
|
||||
#define A3 0x03
|
||||
#define A4 0x04
|
||||
#define A5 0x05
|
||||
#define A6 0x06
|
||||
#define A7 0x07
|
||||
#endif
|
||||
|
||||
/* USART configuration */
|
||||
#ifdef BLUETOOTH_ENABLE
|
||||
|
@ -76,53 +95,9 @@
|
|||
} while(0)
|
||||
# else
|
||||
# error "USART configuration is needed."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// I'm fairly sure these aren't needed, but oh well - Jack
|
||||
|
||||
/*
|
||||
* PS/2 Interrupt configuration
|
||||
*/
|
||||
#ifdef PS2_USE_INT
|
||||
/* uses INT1 for clock line(ATMega32U4) */
|
||||
#define PS2_CLOCK_PORT PORTD
|
||||
#define PS2_CLOCK_PIN PIND
|
||||
#define PS2_CLOCK_DDR DDRD
|
||||
#define PS2_CLOCK_BIT 1
|
||||
|
||||
#define PS2_DATA_PORT PORTD
|
||||
#define PS2_DATA_PIN PIND
|
||||
#define PS2_DATA_DDR DDRD
|
||||
#define PS2_DATA_BIT 0
|
||||
|
||||
#define PS2_INT_INIT() do { \
|
||||
EICRA |= ((1<<ISC11) | \
|
||||
(0<<ISC10)); \
|
||||
} while (0)
|
||||
#define PS2_INT_ON() do { \
|
||||
EIMSK |= (1<<INT1); \
|
||||
} while (0)
|
||||
#define PS2_INT_OFF() do { \
|
||||
EIMSK &= ~(1<<INT1); \
|
||||
} while (0)
|
||||
#define PS2_INT_VECT INT1_vect
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PS/2 Busywait configuration
|
||||
*/
|
||||
#ifdef PS2_USE_BUSYWAIT
|
||||
#define PS2_CLOCK_PORT PORTD
|
||||
#define PS2_CLOCK_PIN PIND
|
||||
#define PS2_CLOCK_DDR DDRD
|
||||
#define PS2_CLOCK_BIT 1
|
||||
|
||||
#define PS2_DATA_PORT PORTD
|
||||
#define PS2_DATA_PIN PIND
|
||||
#define PS2_DATA_DDR DDRD
|
||||
#define PS2_DATA_BIT 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#define API_SYSEX_MAX_SIZE 32
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */
|
||||
#ifndef DYNAMIC_MACROS_H
|
||||
#define DYNAMIC_MACROS_H
|
||||
|
|
68
quantum/fauxclicky.c
Normal file
68
quantum/fauxclicky.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
Copyright 2017 Priyadi Iman Nurcahyo
|
||||
|
||||
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 <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <timer.h>
|
||||
#include <fauxclicky.h>
|
||||
#include <stdbool.h>
|
||||
#include <musical_notes.h>
|
||||
|
||||
__attribute__ ((weak))
|
||||
float fauxclicky_pressed_note[2] = MUSICAL_NOTE(_F3, 2);
|
||||
__attribute__ ((weak))
|
||||
float fauxclicky_released_note[2] = MUSICAL_NOTE(_A3, 2);
|
||||
__attribute__ ((weak))
|
||||
float fauxclicky_beep_note[2] = MUSICAL_NOTE(_C3, 2);
|
||||
|
||||
bool fauxclicky_enabled = true;
|
||||
uint16_t note_start = 0;
|
||||
bool note_playing = false;
|
||||
uint16_t note_period = 0;
|
||||
|
||||
void fauxclicky_init()
|
||||
{
|
||||
// Set port PC6 (OC3A and /OC4A) as output
|
||||
DDRC |= _BV(PORTC6);
|
||||
|
||||
// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
|
||||
TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
|
||||
TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
|
||||
}
|
||||
|
||||
void fauxclicky_stop()
|
||||
{
|
||||
FAUXCLICKY_DISABLE_OUTPUT;
|
||||
note_playing = false;
|
||||
}
|
||||
|
||||
void fauxclicky_play(float note[2]) {
|
||||
if (!fauxclicky_enabled) return;
|
||||
if (note_playing) fauxclicky_stop();
|
||||
FAUXCLICKY_TIMER_PERIOD = (uint16_t)(((float)F_CPU) / (note[0] * FAUXCLICKY_CPU_PRESCALER));
|
||||
FAUXCLICKY_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (note[0] * FAUXCLICKY_CPU_PRESCALER)) / 2);
|
||||
note_playing = true;
|
||||
note_period = (note[1] / 16) * (60 / (float)FAUXCLICKY_TEMPO) * 100; // check this
|
||||
note_start = timer_read();
|
||||
FAUXCLICKY_ENABLE_OUTPUT;
|
||||
}
|
||||
|
||||
void fauxclicky_check() {
|
||||
if (!note_playing) return;
|
||||
|
||||
if (timer_elapsed(note_start) > note_period) {
|
||||
fauxclicky_stop();
|
||||
}
|
||||
}
|
99
quantum/fauxclicky.h
Normal file
99
quantum/fauxclicky.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Copyright 2017 Priyadi Iman Nurcahyo
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
#error "AUDIO_ENABLE and FAUXCLICKY_ENABLE cannot be both enabled"
|
||||
#endif
|
||||
|
||||
#include "musical_notes.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
__attribute__ ((weak))
|
||||
float fauxclicky_pressed_note[2];
|
||||
__attribute__ ((weak))
|
||||
float fauxclicky_released_note[2];
|
||||
__attribute__ ((weak))
|
||||
float fauxclicky_beep_note[2];
|
||||
|
||||
bool fauxclicky_enabled;
|
||||
|
||||
//
|
||||
// tempo in BPM
|
||||
//
|
||||
|
||||
#ifndef FAUXCLICKY_TEMPO
|
||||
#define FAUXCLICKY_TEMPO TEMPO_DEFAULT
|
||||
#endif
|
||||
|
||||
// beep on press
|
||||
#define FAUXCLICKY_ACTION_PRESS fauxclicky_play(fauxclicky_pressed_note)
|
||||
|
||||
// beep on release
|
||||
#define FAUXCLICKY_ACTION_RELEASE fauxclicky_play(fauxclicky_released_note)
|
||||
|
||||
// general purpose beep
|
||||
#define FAUXCLICKY_BEEP fauxclicky_play(fauxclicky_beep_note)
|
||||
|
||||
// enable
|
||||
#define FAUXCLICKY_ON fauxclicky_enabled = true
|
||||
|
||||
// disable
|
||||
#define FAUXCLICKY_OFF do { \
|
||||
fauxclicky_enabled = false; \
|
||||
fauxclicky_stop(); \
|
||||
} while (0)
|
||||
|
||||
// toggle
|
||||
#define FAUXCLICKY_TOGGLE do { \
|
||||
if (fauxclicky_enabled) { \
|
||||
FAUXCLICKY_OFF; \
|
||||
} else { \
|
||||
FAUXCLICKY_ON; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
//
|
||||
// pin configuration
|
||||
//
|
||||
|
||||
#ifndef FAUXCLICKY_CPU_PRESCALER
|
||||
#define FAUXCLICKY_CPU_PRESCALER 8
|
||||
#endif
|
||||
|
||||
#ifndef FAUXCLICKY_ENABLE_OUTPUT
|
||||
#define FAUXCLICKY_ENABLE_OUTPUT TCCR3A |= _BV(COM3A1);
|
||||
#endif
|
||||
|
||||
#ifndef FAUXCLICKY_DISABLE_OUTPUT
|
||||
#define FAUXCLICKY_DISABLE_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
|
||||
#endif
|
||||
|
||||
#ifndef FAUXCLICKY_TIMER_PERIOD
|
||||
#define FAUXCLICKY_TIMER_PERIOD ICR3
|
||||
#endif
|
||||
|
||||
#ifndef FAUXCLICKY_DUTY_CYCLE
|
||||
#define FAUXCLICKY_DUTY_CYCLE OCR3A
|
||||
#endif
|
||||
|
||||
//
|
||||
// definitions
|
||||
//
|
||||
|
||||
void fauxclicky_init(void);
|
||||
void fauxclicky_stop(void);
|
||||
void fauxclicky_play(float note[2]);
|
||||
void fauxclicky_check(void);
|
||||
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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 "keycode_config.h"
|
||||
|
||||
extern keymap_config_t keymap_config;
|
||||
|
@ -71,4 +87,4 @@ uint16_t keycode_config(uint16_t keycode) {
|
|||
default:
|
||||
return keycode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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 "eeconfig.h"
|
||||
#include "keycode.h"
|
||||
|
||||
|
|
311
quantum/keymap.h
311
quantum/keymap.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
|
||||
Copyright 2012-2016 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
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
|
||||
|
@ -38,313 +38,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define RESET QK_RESET
|
||||
#endif
|
||||
|
||||
/* translates key to keycode */
|
||||
#include "quantum_keycodes.h"
|
||||
|
||||
// translates key to keycode
|
||||
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
|
||||
|
||||
// translates function id to action
|
||||
uint16_t keymap_function_id_to_action( uint16_t function_id );
|
||||
|
||||
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
|
||||
extern const uint16_t fn_actions[];
|
||||
|
||||
enum quantum_keycodes {
|
||||
// Ranges used in shortucuts - not to be used directly
|
||||
QK_TMK = 0x0000,
|
||||
QK_TMK_MAX = 0x00FF,
|
||||
QK_MODS = 0x0100,
|
||||
QK_LCTL = 0x0100,
|
||||
QK_LSFT = 0x0200,
|
||||
QK_LALT = 0x0400,
|
||||
QK_LGUI = 0x0800,
|
||||
QK_RCTL = 0x1100,
|
||||
QK_RSFT = 0x1200,
|
||||
QK_RALT = 0x1400,
|
||||
QK_RGUI = 0x1800,
|
||||
QK_MODS_MAX = 0x1FFF,
|
||||
QK_FUNCTION = 0x2000,
|
||||
QK_FUNCTION_MAX = 0x2FFF,
|
||||
QK_MACRO = 0x3000,
|
||||
QK_MACRO_MAX = 0x3FFF,
|
||||
QK_LAYER_TAP = 0x4000,
|
||||
QK_LAYER_TAP_MAX = 0x4FFF,
|
||||
QK_TO = 0x5000,
|
||||
QK_TO_MAX = 0x50FF,
|
||||
QK_MOMENTARY = 0x5100,
|
||||
QK_MOMENTARY_MAX = 0x51FF,
|
||||
QK_DEF_LAYER = 0x5200,
|
||||
QK_DEF_LAYER_MAX = 0x52FF,
|
||||
QK_TOGGLE_LAYER = 0x5300,
|
||||
QK_TOGGLE_LAYER_MAX = 0x53FF,
|
||||
QK_ONE_SHOT_LAYER = 0x5400,
|
||||
QK_ONE_SHOT_LAYER_MAX = 0x54FF,
|
||||
QK_ONE_SHOT_MOD = 0x5500,
|
||||
QK_ONE_SHOT_MOD_MAX = 0x55FF,
|
||||
#ifndef DISABLE_CHORDING
|
||||
QK_CHORDING = 0x5600,
|
||||
QK_CHORDING_MAX = 0x56FF,
|
||||
#endif
|
||||
QK_MOD_TAP = 0x6000,
|
||||
QK_MOD_TAP_MAX = 0x6FFF,
|
||||
QK_TAP_DANCE = 0x7100,
|
||||
QK_TAP_DANCE_MAX = 0x71FF,
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
QK_UNICODE_MAP = 0x7800,
|
||||
QK_UNICODE_MAP_MAX = 0x7FFF,
|
||||
#endif
|
||||
#ifdef UNICODE_ENABLE
|
||||
QK_UNICODE = 0x8000,
|
||||
QK_UNICODE_MAX = 0xFFFF,
|
||||
#endif
|
||||
|
||||
// Loose keycodes - to be used directly
|
||||
|
||||
RESET = 0x7000,
|
||||
DEBUG,
|
||||
MAGIC_SWAP_CONTROL_CAPSLOCK,
|
||||
MAGIC_CAPSLOCK_TO_CONTROL,
|
||||
MAGIC_SWAP_LALT_LGUI,
|
||||
MAGIC_SWAP_RALT_RGUI,
|
||||
MAGIC_NO_GUI,
|
||||
MAGIC_SWAP_GRAVE_ESC,
|
||||
MAGIC_SWAP_BACKSLASH_BACKSPACE,
|
||||
MAGIC_HOST_NKRO,
|
||||
MAGIC_SWAP_ALT_GUI,
|
||||
MAGIC_UNSWAP_CONTROL_CAPSLOCK,
|
||||
MAGIC_UNCAPSLOCK_TO_CONTROL,
|
||||
MAGIC_UNSWAP_LALT_LGUI,
|
||||
MAGIC_UNSWAP_RALT_RGUI,
|
||||
MAGIC_UNNO_GUI,
|
||||
MAGIC_UNSWAP_GRAVE_ESC,
|
||||
MAGIC_UNSWAP_BACKSLASH_BACKSPACE,
|
||||
MAGIC_UNHOST_NKRO,
|
||||
MAGIC_UNSWAP_ALT_GUI,
|
||||
MAGIC_TOGGLE_NKRO,
|
||||
|
||||
// Leader key
|
||||
#ifndef DISABLE_LEADER
|
||||
KC_LEAD,
|
||||
#endif
|
||||
|
||||
// Audio on/off/toggle
|
||||
AU_ON,
|
||||
AU_OFF,
|
||||
AU_TOG,
|
||||
|
||||
// Music mode on/off/toggle
|
||||
MU_ON,
|
||||
MU_OFF,
|
||||
MU_TOG,
|
||||
|
||||
// Music voice iterate
|
||||
MUV_IN,
|
||||
MUV_DE,
|
||||
|
||||
// Midi mode on/off
|
||||
MIDI_ON,
|
||||
MIDI_OFF,
|
||||
|
||||
// Backlight functionality
|
||||
BL_0,
|
||||
BL_1,
|
||||
BL_2,
|
||||
BL_3,
|
||||
BL_4,
|
||||
BL_5,
|
||||
BL_6,
|
||||
BL_7,
|
||||
BL_8,
|
||||
BL_9,
|
||||
BL_10,
|
||||
BL_11,
|
||||
BL_12,
|
||||
BL_13,
|
||||
BL_14,
|
||||
BL_15,
|
||||
BL_DEC,
|
||||
BL_INC,
|
||||
BL_TOGG,
|
||||
BL_STEP,
|
||||
|
||||
// RGB functionality
|
||||
RGB_TOG,
|
||||
RGB_MOD,
|
||||
RGB_HUI,
|
||||
RGB_HUD,
|
||||
RGB_SAI,
|
||||
RGB_SAD,
|
||||
RGB_VAI,
|
||||
RGB_VAD,
|
||||
|
||||
// Left shift, open paren
|
||||
KC_LSPO,
|
||||
|
||||
// Right shift, close paren
|
||||
KC_RSPC,
|
||||
|
||||
// always leave at the end
|
||||
SAFE_RANGE
|
||||
};
|
||||
|
||||
// Ability to use mods in layouts
|
||||
#define LCTL(kc) (kc | QK_LCTL)
|
||||
#define LSFT(kc) (kc | QK_LSFT)
|
||||
#define LALT(kc) (kc | QK_LALT)
|
||||
#define LGUI(kc) (kc | QK_LGUI)
|
||||
#define RCTL(kc) (kc | QK_RCTL)
|
||||
#define RSFT(kc) (kc | QK_RSFT)
|
||||
#define RALT(kc) (kc | QK_RALT)
|
||||
#define RGUI(kc) (kc | QK_RGUI)
|
||||
|
||||
#define HYPR(kc) (kc | QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI)
|
||||
#define MEH(kc) (kc | QK_LCTL | QK_LSFT | QK_LALT)
|
||||
#define LCAG(kc) (kc | QK_LCTL | QK_LALT | QK_LGUI)
|
||||
#define ALTG(kc) (kc | QK_RCTL | QK_RALT)
|
||||
|
||||
#define MOD_HYPR 0xf
|
||||
#define MOD_MEH 0x7
|
||||
|
||||
|
||||
// Aliases for shifted symbols
|
||||
// Each key has a 4-letter code, and some have longer aliases too.
|
||||
// While the long aliases are descriptive, the 4-letter codes
|
||||
// make for nicer grid layouts (everything lines up), and are
|
||||
// the preferred style for Quantum.
|
||||
#define KC_TILD LSFT(KC_GRV) // ~
|
||||
#define KC_TILDE KC_TILD
|
||||
|
||||
#define KC_EXLM LSFT(KC_1) // !
|
||||
#define KC_EXCLAIM KC_EXLM
|
||||
|
||||
#define KC_AT LSFT(KC_2) // @
|
||||
|
||||
#define KC_HASH LSFT(KC_3) // #
|
||||
|
||||
#define KC_DLR LSFT(KC_4) // $
|
||||
#define KC_DOLLAR KC_DLR
|
||||
|
||||
#define KC_PERC LSFT(KC_5) // %
|
||||
#define KC_PERCENT KC_PERC
|
||||
|
||||
#define KC_CIRC LSFT(KC_6) // ^
|
||||
#define KC_CIRCUMFLEX KC_CIRC
|
||||
|
||||
#define KC_AMPR LSFT(KC_7) // &
|
||||
#define KC_AMPERSAND KC_AMPR
|
||||
|
||||
#define KC_ASTR LSFT(KC_8) // *
|
||||
#define KC_ASTERISK KC_ASTR
|
||||
|
||||
#define KC_LPRN LSFT(KC_9) // (
|
||||
#define KC_LEFT_PAREN KC_LPRN
|
||||
|
||||
#define KC_RPRN LSFT(KC_0) // )
|
||||
#define KC_RIGHT_PAREN KC_RPRN
|
||||
|
||||
#define KC_UNDS LSFT(KC_MINS) // _
|
||||
#define KC_UNDERSCORE KC_UNDS
|
||||
|
||||
#define KC_PLUS LSFT(KC_EQL) // +
|
||||
|
||||
#define KC_LCBR LSFT(KC_LBRC) // {
|
||||
#define KC_LEFT_CURLY_BRACE KC_LCBR
|
||||
|
||||
#define KC_RCBR LSFT(KC_RBRC) // }
|
||||
#define KC_RIGHT_CURLY_BRACE KC_RCBR
|
||||
|
||||
#define KC_LABK LSFT(KC_COMM) // <
|
||||
#define KC_LEFT_ANGLE_BRACKET KC_LABK
|
||||
|
||||
#define KC_RABK LSFT(KC_DOT) // >
|
||||
#define KC_RIGHT_ANGLE_BRACKET KC_RABK
|
||||
|
||||
#define KC_COLN LSFT(KC_SCLN) // :
|
||||
#define KC_COLON KC_COLN
|
||||
|
||||
#define KC_PIPE LSFT(KC_BSLS) // |
|
||||
|
||||
#define KC_LT LSFT(KC_COMM) // <
|
||||
|
||||
#define KC_GT LSFT(KC_DOT) // >
|
||||
|
||||
#define KC_QUES LSFT(KC_SLSH) // ?
|
||||
#define KC_QUESTION KC_QUES
|
||||
|
||||
#define KC_DQT LSFT(KC_QUOT) // "
|
||||
#define KC_DOUBLE_QUOTE KC_DQT
|
||||
#define KC_DQUO KC_DQT
|
||||
|
||||
#define KC_DELT KC_DELETE // Del key (four letter code)
|
||||
|
||||
// Alias for function layers than expand past FN31
|
||||
#define FUNC(kc) (kc | QK_FUNCTION)
|
||||
|
||||
// Aliases
|
||||
#define S(kc) LSFT(kc)
|
||||
#define F(kc) FUNC(kc)
|
||||
|
||||
#define M(kc) (kc | QK_MACRO)
|
||||
|
||||
#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
|
||||
|
||||
// L-ayer, T-ap - 256 keycode max, 16 layer max
|
||||
#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
|
||||
|
||||
#define AG_SWAP MAGIC_SWAP_ALT_GUI
|
||||
#define AG_NORM MAGIC_UNSWAP_ALT_GUI
|
||||
|
||||
#define BL_ON BL_9
|
||||
#define BL_OFF BL_0
|
||||
|
||||
#define MI_ON MIDI_ON
|
||||
#define MI_OFF MIDI_OFF
|
||||
|
||||
// GOTO layer - 16 layers max
|
||||
// when:
|
||||
// ON_PRESS = 1
|
||||
// ON_RELEASE = 2
|
||||
// Unless you have a good reason not to do so, prefer ON_PRESS (1) as your default.
|
||||
// In fact, we changed it to assume ON_PRESS for sanity/simplicity. If needed, you can add your own
|
||||
// keycode modeled after the old version, kept below for this.
|
||||
/* #define TO(layer, when) (layer | QK_TO | (when << 0x4)) */
|
||||
#define TO(layer) (layer | QK_TO | (ON_PRESS << 0x4))
|
||||
|
||||
// Momentary switch layer - 256 layer max
|
||||
#define MO(layer) (layer | QK_MOMENTARY)
|
||||
|
||||
// Set default layer - 256 layer max
|
||||
#define DF(layer) (layer | QK_DEF_LAYER)
|
||||
|
||||
// Toggle to layer - 256 layer max
|
||||
#define TG(layer) (layer | QK_TOGGLE_LAYER)
|
||||
|
||||
// One-shot layer - 256 layer max
|
||||
#define OSL(layer) (layer | QK_ONE_SHOT_LAYER)
|
||||
|
||||
// One-shot mod
|
||||
#define OSM(mod) (mod | QK_ONE_SHOT_MOD)
|
||||
|
||||
// M-od, T-ap - 256 keycode max
|
||||
#define MT(mod, kc) (kc | QK_MOD_TAP | ((mod & 0xF) << 8))
|
||||
#define CTL_T(kc) MT(MOD_LCTL, kc)
|
||||
#define SFT_T(kc) MT(MOD_LSFT, kc)
|
||||
#define ALT_T(kc) MT(MOD_LALT, kc)
|
||||
#define GUI_T(kc) MT(MOD_LGUI, kc)
|
||||
#define C_S_T(kc) MT((MOD_LCTL | MOD_LSFT), kc) // Control + Shift e.g. for gnome-terminal
|
||||
#define MEH_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT), kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl
|
||||
#define LCAG_T(kc) MT((MOD_LCTL | MOD_LALT | MOD_LGUI), kc) // Left control alt and gui
|
||||
#define ALL_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI), kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
|
||||
|
||||
// Dedicated keycode versions for Hyper and Meh, if you want to use them as standalone keys rather than mod-tap
|
||||
#define KC_HYPR HYPR(KC_NO)
|
||||
#define KC_MEH MEH(KC_NO)
|
||||
|
||||
#ifdef UNICODE_ENABLE
|
||||
// For sending unicode codes.
|
||||
// You may not send codes over 7FFF -- this supports most of UTF8.
|
||||
// To have a key that sends out Œ, go UC(0x0152)
|
||||
#define UNICODE(n) (n | QK_UNICODE)
|
||||
#define UC(n) UNICODE(n)
|
||||
#endif
|
||||
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
#define X(n) (n | QK_UNICODE_MAP)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
|
||||
Copyright 2012-2017 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
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
|
||||
|
@ -48,12 +48,10 @@ action_t action_for_key(uint8_t layer, keypos_t key)
|
|||
|
||||
action_t action;
|
||||
uint8_t action_layer, when, mod;
|
||||
// The arm-none-eabi compiler generates out of bounds warnings when using the fn_actions directly for some reason
|
||||
const uint16_t* actions = fn_actions;
|
||||
|
||||
switch (keycode) {
|
||||
case KC_FN0 ... KC_FN31:
|
||||
action.code = pgm_read_word(&actions[FN_INDEX(keycode)]);
|
||||
action.code = keymap_function_id_to_action(FN_INDEX(keycode));
|
||||
break;
|
||||
case KC_A ... KC_EXSEL:
|
||||
case KC_LCTRL ... KC_RGUI:
|
||||
|
@ -79,10 +77,13 @@ action_t action_for_key(uint8_t layer, keypos_t key)
|
|||
case QK_FUNCTION ... QK_FUNCTION_MAX: ;
|
||||
// Is a shortcut for function action_layer, pull last 12bits
|
||||
// This means we have 4,096 FN macros at our disposal
|
||||
action.code = pgm_read_word(&actions[(int)keycode & 0xFFF]);
|
||||
action.code = keymap_function_id_to_action( (int)keycode & 0xFFF );
|
||||
break;
|
||||
case QK_MACRO ... QK_MACRO_MAX:
|
||||
action.code = ACTION_MACRO(keycode & 0xFF);
|
||||
if (keycode & 0x800) // tap macros have upper bit set
|
||||
action.code = ACTION_MACRO_TAP(keycode & 0xFF);
|
||||
else
|
||||
action.code = ACTION_MACRO(keycode & 0xFF);
|
||||
break;
|
||||
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
|
||||
action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
|
||||
|
@ -118,8 +119,11 @@ action_t action_for_key(uint8_t layer, keypos_t key)
|
|||
mod = keycode & 0xFF;
|
||||
action.code = ACTION_MODS_ONESHOT(mod);
|
||||
break;
|
||||
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
|
||||
action.code = ACTION_LAYER_TAP_TOGGLE(keycode & 0xFF);
|
||||
break;
|
||||
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
|
||||
action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
|
||||
action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0x1F, keycode & 0xFF);
|
||||
break;
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
case BL_0 ... BL_15:
|
||||
|
@ -163,9 +167,17 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
|
|||
{
|
||||
}
|
||||
|
||||
/* translates key to keycode */
|
||||
// translates key to keycode
|
||||
__attribute__ ((weak))
|
||||
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
|
||||
{
|
||||
// Read entire word (16bits)
|
||||
return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]);
|
||||
}
|
||||
|
||||
// translates function id to action
|
||||
__attribute__ ((weak))
|
||||
uint16_t keymap_function_id_to_action( uint16_t function_id )
|
||||
{
|
||||
return pgm_read_word(&fn_actions[function_id]);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 Didier Loiseau
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
/* Keymap macros for the French BÉPO layout - http://bepo.fr */
|
||||
#ifndef KEYMAP_BEPO_H
|
||||
#define KEYMAP_BEPO_H
|
||||
|
|
74
quantum/keymap_extras/keymap_br_abnt2.h
Normal file
74
quantum/keymap_extras/keymap_br_abnt2.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* Copyright 2017 Potiguar Faga
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef KEYMAP_BR_ABNT2_H
|
||||
#define KEYMAP_BR_ABNT2_H
|
||||
|
||||
#include "keymap_common.h"
|
||||
|
||||
/* Scan codes for the Brazilian ABNT2 keyboard layout */
|
||||
|
||||
#define BR_CCDL KC_SCLN // Ç same scancode as ;: on US layout
|
||||
#define BR_SCLN KC_SLSH // ;: same scancode as /? on US layout
|
||||
#define BR_QUOT KC_GRV // '" same scancode as `~ on US layout
|
||||
#define BR_TILD KC_QUOT // ~^ dead keys, same scancode as '" on US layout
|
||||
#define BR_ACUT KC_LBRC // ´` dead keys, same scancode as [{ on US layout
|
||||
#define BR_LBRC KC_RBRC // [{ same scancode as ]} on US layout
|
||||
#define BR_RBRC KC_BSLS // ]} same scancode as \| on US layout
|
||||
#define BR_BSLS KC_NUBS // \| uses the non-US hash scancode (#~, sometimes §±)
|
||||
#define BR_SLSH KC_INT1 // /? uses the INTL1 scancode
|
||||
|
||||
#define BR_COLN LSFT(BR_SCLN) // shifted :
|
||||
#define BR_DQT LSFT(BR_QUOT) // shifted "
|
||||
#define BR_CIRC LSFT(BR_TILD) // shifted ^ (dead key)
|
||||
#define BR_GRAV LSFT(BR_ACUT) // shifted ` (dead key)
|
||||
#define BR_LCBR LSFT(BR_LBRC) // shifted {
|
||||
#define BR_RCBR LSFT(BR_RBRC) // shifted }
|
||||
#define BR_PIPE LSFT(BR_BSLS) // shifted |
|
||||
#define BR_QUES LSFT(BR_SLSH) // shifted ?
|
||||
#define BR_TRMA LSFT(KC_6) // shifted ¨ (dead key - trema accent)
|
||||
|
||||
// On the ABNT2 the keypad comma and the keypad dot scancodes are switched
|
||||
// (presumably because in Brazil comma is used as the decimal separator)
|
||||
#define BR_KPDT KC_KP_COMMA // keypad .
|
||||
#define BR_KPCM KC_KP_DOT // keypad ,
|
||||
|
||||
#define BR_1UP LALT(KC_1) // 1 superscript ¹ alt+1
|
||||
#define BR_2UP LALT(KC_2) // 2 superscript ² alt+2
|
||||
#define BR_3UP LALT(KC_3) // 3 superscript ³ alt+3
|
||||
#define BR_PND LALT(KC_4) // Pound sign £ alt+4
|
||||
#define BR_CENT LALT(KC_5) // Cent sign ¢ alt+5
|
||||
#define BR_NOT LALT(KC_6) // Not sign ¬ alt+6
|
||||
#define BR_SECT LALT(KC_EQL) // Section sign § alt+=
|
||||
#define BR_FORD LALT(BR_LBRC) // Feminine Ordinal Sign ª alt+[
|
||||
#define BR_MORD LALT(BR_RBRC) // Masculine Ordinal Sign º alt+]
|
||||
#define BR_DGRE LALT(BR_SLSH) // Degree sign ° alt+/
|
||||
|
||||
#define BR_EURO LALT(KC_E) // Euro sign € alt+e
|
||||
#define BR_NDTD LALT(BR_TILD) // Non-dead key tilde ~ alt+~
|
||||
#define BR_NDAC LALT(BR_ACUT) // Non-dead key acute accent ´ alt+´
|
||||
#define BR_NDGV LALT(BR_QUOT) // Non-dead key grave accent ` alt+'
|
||||
#define BR_NDCR LALT(BR_CIRC) // Non-dead key circumflex accent ^ alt+^ (alt+shift+~)
|
||||
#define BR_NDTR LALT(BR_TRMA) // Non-dead key trema accent ¨ alt+¨ (alt+shift+6)
|
||||
|
||||
// For 101-key keyboard layouts, the ABNT2 layout allows
|
||||
// the slash and question mark to be typed using alt+q and alt+w.
|
||||
// The shortcuts are provided here for completeness' sake,
|
||||
// but it's recommended to use BR_SLSH and BR_QUES instead
|
||||
#define BR_ASLS LALT(KC_Q)
|
||||
#define BR_AQST LALT(KC_W)
|
||||
|
||||
#endif
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 Didier Loiseau
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_CANADIAN_MULTILINGUAG_H
|
||||
#define KEYMAP_CANADIAN_MULTILINGUAG_H
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2015-2016 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_COLEMAK_H
|
||||
#define KEYMAP_COLEMAK_H
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2015-2016 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_DVORAK_H
|
||||
#define KEYMAP_DVORAK_H
|
||||
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 Artyom Mironov
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef KEYMAP_DVP_H
|
||||
#define KEYMAP_DVP_H
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 Vincent Pochet
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_FR_CH
|
||||
#define KEYMAP_FR_CH
|
||||
|
||||
|
|
|
@ -1,10 +1,27 @@
|
|||
/* Copyright 2015-2016 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_FRENCH_H
|
||||
#define KEYMAP_FRENCH_H
|
||||
|
||||
#include "keymap.h"
|
||||
|
||||
// Alt gr
|
||||
#ifndef ALGR
|
||||
#define ALGR(kc) RALT(kc)
|
||||
#endif
|
||||
#define NO_ALGR KC_RALT
|
||||
|
||||
// Normal characters
|
||||
|
@ -72,7 +89,7 @@
|
|||
#define FR_PIPE ALGR(KC_6)
|
||||
#define FR_GRV ALGR(KC_7)
|
||||
#define FR_BSLS ALGR(KC_8)
|
||||
#define FR_CIRC ALGR(KC_9)
|
||||
#define FR_CCIRC ALGR(KC_9)
|
||||
#define FR_AT ALGR(KC_0)
|
||||
#define FR_RBRC ALGR(FR_RPRN)
|
||||
#define FR_RCBR ALGR(FR_EQL)
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 Sébastien Pérochon
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_FRENCH_OSX_H
|
||||
#define KEYMAP_FRENCH_OSX_H
|
||||
|
||||
|
@ -74,4 +89,4 @@
|
|||
#define FR_PIPE LSFT(LALT(KC_L))
|
||||
#define FR_BSLS LSFT(LALT(FR_COLN))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2015-2016 Matthias Schmidtt
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef KEYMAP_GERMAN
|
||||
#define KEYMAP_GERMAN
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 heartsekai
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_SWISS_GERMAN
|
||||
#define KEYMAP_SWISS_GERMAN
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 Stephen Bösebeck
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_GERMAN_OSX
|
||||
#define KEYMAP_GERMAN_OSX
|
||||
|
||||
|
|
77
quantum/keymap_extras/keymap_jp.h
Normal file
77
quantum/keymap_extras/keymap_jp.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* Copyright 2016 h-youhei
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* JP106-layout (Japanese Standard)
|
||||
*
|
||||
* For more information, see
|
||||
* http://www2d.biglobe.ne.jp/~msyk/keyboard/layout/usbkeycode.html
|
||||
* note: This website is written in Japanese.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef KEYMAP_JP_H
|
||||
#define KEYMAP_JP_H
|
||||
|
||||
|
||||
#include "keymap.h"
|
||||
|
||||
|
||||
#define JP_ZHTG KC_GRV // hankaku/zenkaku|kanzi
|
||||
#define JP_YEN KC_INT3 // yen, |
|
||||
#define JP_CIRC KC_EQL // ^, ~
|
||||
#define JP_AT KC_LBRC // @, `
|
||||
#define JP_LBRC KC_RBRC // [, {
|
||||
#define JP_COLN KC_QUOT // :, *
|
||||
#define JP_RBRC KC_NUHS // ], }
|
||||
#define JP_BSLS KC_INT1 // \, _
|
||||
#define JP_MHEN KC_INT5 // muhenkan
|
||||
#define JP_HENK KC_INT4 // henkan
|
||||
#define JP_KANA KC_INT2 // katakana/hiragana|ro-mazi
|
||||
|
||||
|
||||
//Aliases for shifted symbols
|
||||
#define JP_DQT LSFT(KC_2) // "
|
||||
#define JP_AMPR LSFT(KC_6) // &
|
||||
#define JP_QUOT LSFT(KC_7) // '
|
||||
#define JP_LPRN LSFT(KC_8) // (
|
||||
#define JP_RPRN LSFT(KC_9) // )
|
||||
#define JP_EQL LSFT(KC_MINS) // =
|
||||
#define JP_TILD LSFT(JP_CIRC) // ~
|
||||
#define JP_PIPE LSFT(JP_YEN) // |
|
||||
#define JP_GRV LSFT(JP_AT) // `
|
||||
#define JP_LCBR LSFT(JP_LBRC) // {
|
||||
#define JP_PLUS LSFT(KC_SCLN) // +
|
||||
#define JP_ASTR LSFT(JP_COLN) // *
|
||||
#define JP_RCBR LSFT(JP_RBRC) // }
|
||||
#define JP_UNDS LSFT(JP_BSLS) // _
|
||||
|
||||
|
||||
// These symbols are correspond to US101-layout.
|
||||
#define JP_MINS KC_MINS // -
|
||||
#define JP_SCLN KC_SCLN // ;
|
||||
#define JP_COMM KC_COMM // ,
|
||||
#define JP_DOT KC_DOT // .
|
||||
#define JP_SLSH KC_SLSH // /
|
||||
// shifted
|
||||
#define JP_EXLM KC_EXLM // !
|
||||
#define JP_HASH KC_HASH // #
|
||||
#define JP_DLR KC_DLR // $
|
||||
#define JP_PERC KC_PERC // %
|
||||
#define JP_LT KC_LT // <
|
||||
#define JP_GT KC_GT // >
|
||||
#define JP_QUES KC_QUES // ?
|
||||
|
||||
|
||||
#endif
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 Matthias Schmitt
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_NEO2
|
||||
#define KEYMAP_NEO2
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2015-2016 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_NORDIC_H
|
||||
#define KEYMAP_NORDIC_H
|
||||
|
||||
|
@ -13,7 +28,7 @@
|
|||
#define NO_ACUT KC_EQL
|
||||
|
||||
#define NO_AM KC_LBRC
|
||||
#define NO_QUOT KC_RBRC
|
||||
#define NO_QUOT KC_RBRC // this is the "umlaut" char on Nordic keyboards, Apple layout
|
||||
#define NO_AE KC_SCLN
|
||||
#define NO_OSLH KC_QUOT
|
||||
#define NO_APOS KC_NUHS
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_NORWEGIAN_H
|
||||
#define KEYMAP_NORWEGIAN_H
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 James Kay
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_PLOVER_H
|
||||
#define KEYMAP_PLOVER_H
|
||||
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
#ifndef KEYMAP_RUSSIAN_H
|
||||
#define KEYMAP_RUSSIAN_H
|
||||
|
||||
#include "keymap.h"
|
||||
|
||||
// Normal Chracters // reg SHIFT
|
||||
#define RU_A KC_F // а and А
|
||||
#define RU_BE KC_COMM // б and Б
|
||||
#define RU_VE KC_D // в and В
|
||||
#define RU_GHE KC_U // г and Г
|
||||
#define RU_DE KC_L // д and Д
|
||||
#define RU_IE KC_T // е and Е
|
||||
#define RU_IO KC_GRV // ё and Ё
|
||||
#define RU_ZHE KC_SCLN // ж and Ж
|
||||
#define RU_ZE KC_P // з and З
|
||||
#define RU_I KC_B // и and И
|
||||
#define RU_SRT_I KC_Q // й and Й
|
||||
#define RU_KA KC_R // к and К
|
||||
#define RU_EL KC_K // л and Л
|
||||
#define RU_EM KC_V // м and М
|
||||
#define RU_EN KC_Y // н and Н
|
||||
#define RU_O KC_J // о and О
|
||||
#define RU_PE KC_G // п and П
|
||||
#define RU_ER KC_H // р and Р
|
||||
#define RU_ES KC_C // с and С
|
||||
#define RU_TE KC_N // т and Т
|
||||
#define RU_U KC_E // у and У
|
||||
#define RU_EF KC_A // ф and Ф
|
||||
#define RU_HA KC_LBRC // х and Х
|
||||
#define RU_TSE KC_W // ц and Ц
|
||||
#define RU_CHE KC_X // ч and Ч
|
||||
#define RU_SHA KC_I // ш and Ш
|
||||
#define RU_SHCHA KC_O // щ and Щ
|
||||
#define RU_HSIGN KC_RBRC // ъ and Ъ
|
||||
#define RU_YERU KC_S // ы and Ы
|
||||
#define RU_SSIGN KC_M // ь and Ь
|
||||
#define RU_E KC_QUOT // э and Э
|
||||
#define RU_YU KC_DOT // ю and Ю
|
||||
#define RU_YA KC_Z // я and Я
|
||||
|
||||
#define RU_1 KC_1 // 1 and !
|
||||
#define RU_2 KC_2 // 2 and "
|
||||
#define RU_3 KC_3 // 3 and №
|
||||
#define RU_4 KC_4 // 4 and ;
|
||||
#define RU_5 KC_5 // 5 and %
|
||||
#define RU_6 KC_6 // 6 and :
|
||||
#define RU_7 KC_7 // 7 and ?
|
||||
#define RU_8 KC_8 // 8 and *
|
||||
#define RU_9 KC_9 // 9 and (
|
||||
#define RU_0 KC_0 // 0 and )
|
||||
|
||||
#define RU_MINS KC_MINS // - and _
|
||||
#define RU_EQL KC_EQL // = and +
|
||||
#define RU_BSLS KC_BSLS // \ and /
|
||||
#define RU_DOT KC_SLSH // . and ,
|
||||
|
||||
// Shifted Chracters
|
||||
#define RU_EXLM LSFT(RU_1) // !
|
||||
#define RU_DQUT LSFT(RU_2) // "
|
||||
#define RU_NMRO LSFT(RU_3) // №
|
||||
#define RU_SCLN LSFT(RU_4) // ;
|
||||
#define RU_PERC LSFT(RU_5) // %
|
||||
#define RU_COLN LSFT(RU_6) // :
|
||||
#define RU_QUES LSFT(RU_7) // ?
|
||||
#define RU_ASTR LSFT(RU_8) // *
|
||||
#define RU_LPRN LSFT(RU_9) // (
|
||||
#define RU_RPRN LSFT(RU_0) // )
|
||||
|
||||
#define RU_UNDR LSFT(RU_MINS) // _
|
||||
#define RU_PLUS LSFT(RU_EQL) // +
|
||||
#define RU_SLSH LSFT(RU_BSLS) // /
|
||||
#define RU_COMM LSFT(RU_DOT) // ,
|
||||
|
||||
// Alt Gr-ed characters
|
||||
#define RU_RUBL RALT(RU_8) // ₽
|
||||
|
||||
#endif
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2015-2016 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_SPANISH_H
|
||||
#define KEYMAP_SPANISH_H
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2015-2016 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/>.
|
||||
*/
|
||||
#ifndef KEYMAP_UK_H
|
||||
#define KEYMAP_UK_H
|
||||
|
||||
|
|
|
@ -1,163 +0,0 @@
|
|||
#ifndef KEYMAP_CYRILLIC_H
|
||||
#define KEYMAP_CYRILLIC_H
|
||||
|
||||
#include "keymap.h"
|
||||
|
||||
/*
|
||||
* This is based off of
|
||||
* https://en.wikipedia.org/wiki/Cyrillic_script
|
||||
*
|
||||
* Unicode is iffy, a software implementation is preferred
|
||||
*/
|
||||
|
||||
// Capital Char russian/ukrainian/bulgarian
|
||||
#define CY_A UC(0x0410) // А rus ukr bul
|
||||
#define CY_BE UC(0x0411) // Б rus ukr bul
|
||||
#define CY_VE UC(0x0412) // В rus ukr bul
|
||||
#define CY_GHE UC(0x0413) // Г rus ukr bul
|
||||
#define CY_GHEUP UC(0x0490) // Ґ ukr
|
||||
#define CY_DE UC(0x0414) // Д rus ukr bul
|
||||
#define CY_DJE UC(0x0402) // Ђ
|
||||
#define CY_GJE UC(0x0403) // Ѓ
|
||||
#define CY_IE UC(0x0415) // Е rus ukr bul
|
||||
#define CY_IO UC(0x0401) // Ё rus
|
||||
#define CY_UIE UC(0x0404) // Є ukr
|
||||
#define CY_ZHE UC(0x0416) // Ж rus ukr bul
|
||||
#define CY_ZE UC(0x0417) // З rus ukr bul
|
||||
#define CY_DZE UC(0x0405) // Ѕ
|
||||
#define CY_I UC(0x0418) // И rus ukr bul
|
||||
#define CY_B_U_I UC(0x0406) // І ukr
|
||||
#define CY_YI UC(0x0407) // Ї ukr
|
||||
#define CY_SRT_I UC(0x0419) // Й rus ukr bul
|
||||
#define CY_JE UC(0x0408) // Ј
|
||||
#define CY_KA UC(0x041a) // К rus ukr bul
|
||||
#define CY_EL UC(0x041b) // Л rus ukr bul
|
||||
#define CY_LJE UC(0x0409) // Љ
|
||||
#define CY_EM UC(0x041c) // М rus ukr bul
|
||||
#define CY_EN UC(0x041d) // Н rus ukr bul
|
||||
#define CY_NJE UC(0x040a) // Њ
|
||||
#define CY_O UC(0x041e) // О rus ukr bul
|
||||
#define CY_PE UC(0x041f) // П rus ukr bul
|
||||
#define CY_ER UC(0x0420) // Р rus ukr bul
|
||||
#define CY_ES UC(0x0421) // С rus ukr bul
|
||||
#define CY_TE UC(0x0422) // Т rus ukr bul
|
||||
#define CY_TSHE UC(0x040b) // Ћ
|
||||
#define CY_KJE UC(0x040c) // Ќ
|
||||
#define CY_U UC(0x0423) // У rus ukr bul
|
||||
#define CY_SRT_U UC(0x040e) // Ў
|
||||
#define CY_EF UC(0x0424) // Ф rus ukr bul
|
||||
#define CY_HA UC(0x0425) // Х rus bul
|
||||
#define CY_TSE UC(0x0426) // Ц rus ukr bul
|
||||
#define CY_CHE UC(0x0427) // Ч rus ukr bul
|
||||
#define CY_DZHE UC(0x040f) // Џ
|
||||
#define CY_SHA UC(0x0428) // Ш rus ukr bul
|
||||
#define CY_SHCHA UC(0x0429) // Щ rus ukr bul
|
||||
#define CY_HSIGN UC(0x042a) // Ъ rus bul
|
||||
#define CY_YERU UC(0x042b) // Ы rus
|
||||
#define CY_SSIGN UC(0x042c) // Ь rus ukr bul
|
||||
#define CY_E UC(0x042d) // Э rus
|
||||
#define CY_YU UC(0x042e) // Ю rus ukr bul
|
||||
#define CY_YA UC(0x042f) // Я rus ukr bul
|
||||
// Important Cyrillic non-Slavic letters
|
||||
#define CY_PALOCHKA UC(0x04c0) // Ӏ
|
||||
#define CY_SCHWA UC(0x04d8) // Ә
|
||||
#define CY_GHE_S UC(0x0492) // Ғ
|
||||
#define CY_ZE_D UC(0x0498) // Ҙ
|
||||
#define CY_ES_D UC(0x04aa) // Ҫ
|
||||
#define CY_BR_KA UC(0x04a0) // Ҡ
|
||||
#define CY_ZHE_D UC(0x0496) // Җ
|
||||
#define CY_KA_D UC(0x049a) // Қ
|
||||
#define CY_EN_D UC(0x04a2) // Ң
|
||||
#define CY_ENGHE UC(0x04a4) // Ҥ
|
||||
#define CY_BRD_O UC(0x04e8) // Ө
|
||||
#define CY_STR_U UC(0x04ae) // Ү
|
||||
#define CY_S_U_S UC(0x04b0) // Ұ
|
||||
#define CY_SHHA UC(0x04ba) // Һ
|
||||
#define CY_HA_D UC(0x04b2) // Ҳ
|
||||
|
||||
|
||||
// Small
|
||||
#define CY_a UC(0x0430) // a rus ukr bul
|
||||
#define CY_be UC(0x0431) // б rus ukr bul
|
||||
#define CY_ve UC(0x0432) // в rus ukr bul
|
||||
#define CY_ghe UC(0x0433) // г rus ukr bul
|
||||
#define CY_gheup UC(0x0491) // ґ ukr
|
||||
#define CY_de UC(0x0434) // д rus ukr bul
|
||||
#define CY_dje UC(0x0452) // ђ
|
||||
#define CY_gje UC(0x0453) // ѓ
|
||||
#define CY_ie UC(0x0435) // е rus ukr bul
|
||||
#define CY_io UC(0x0451) // ё rus
|
||||
#define CY_uie UC(0x0454) // є ukr
|
||||
#define CY_zhe UC(0x0436) // ж rus ukr bul
|
||||
#define CY_ze UC(0x0437) // з rus ukr bul
|
||||
#define CY_dze UC(0x0455) // ѕ
|
||||
#define CY_i UC(0x0438) // и rus ukr bul
|
||||
#define CY_b_u_i UC(0x0456) // і ukr
|
||||
#define CY_yi UC(0x0457) // ї ukr
|
||||
#define CY_srt_i UC(0x0439) // й rus ukr bul
|
||||
#define CY_je UC(0x0458) // ј
|
||||
#define CY_ka UC(0x043a) // к rus ukr bul
|
||||
#define CY_el UC(0x043b) // л rus ukr bul
|
||||
#define CY_lje UC(0x0459) // љ
|
||||
#define CY_em UC(0x043c) // м rus ukr bul
|
||||
#define CY_en UC(0x043d) // н rus ukr bul
|
||||
#define CY_nje UC(0x045a) // њ
|
||||
#define CY_o UC(0x043e) // о rus ukr bul
|
||||
#define CY_pe UC(0x043f) // п rus ukr bul
|
||||
#define CY_er UC(0x0440) // р rus ukr bul
|
||||
#define CY_es UC(0x0441) // с rus ukr bul
|
||||
#define CY_te UC(0x0442) // т rus ukr bul
|
||||
#define CY_tshe UC(0x045b) // ћ
|
||||
#define CY_kje UC(0x045c) // ќ
|
||||
#define CY_u UC(0x0443) // у rus ukr bul
|
||||
#define CY_srt_u UC(0x045e) // ў
|
||||
#define CY_ef UC(0x0444) // ф rus ukr bul
|
||||
#define CY_ha UC(0x0445) // х rus ukr bul
|
||||
#define CY_tse UC(0x0446) // ц rus ukr bul
|
||||
#define CY_che UC(0x0447) // ч rus ukr bul
|
||||
#define CY_dzhe UC(0x045f) // џ
|
||||
#define CY_sha UC(0x0448) // ш rus ukr bul
|
||||
#define CY_shcha UC(0x0449) // щ rus ukr bul
|
||||
#define CY_hsign UC(0x044a) // ъ rus bul
|
||||
#define CY_yeru UC(0x044b) // ы rus
|
||||
#define CY_ssign UC(0x044c) // ь rus ukr bul
|
||||
#define CY_e UC(0x044d) // э rus
|
||||
#define CY_yu UC(0x044e) // ю rus ukr bul
|
||||
#define CY_ya UC(0x044f) // я rus ukr bul
|
||||
// Important Cyrillic non-Slavic letters
|
||||
#define CY_palochka UC(0x04cf) // ӏ
|
||||
#define CY_schwa UC(0x04d9) // ә
|
||||
#define CY_ghe_s UC(0x0493) // ғ
|
||||
#define CY_ze_d UC(0x0499) // ҙ
|
||||
#define CY_es_d UC(0x04ab) // ҫ
|
||||
#define CY_br_ka UC(0x04a1) // ҡ
|
||||
#define CY_zhe_d UC(0x0497) // җ
|
||||
#define CY_ka_d UC(0x049b) // қ
|
||||
#define CY_en_d UC(0x04a3) // ң
|
||||
#define CY_enghe UC(0x04a5) // ҥ
|
||||
#define CY_brd_o UC(0x04e9) // ө
|
||||
#define CY_str_u UC(0x04af) // ү
|
||||
#define CY_s_u_s UC(0x04b1) // ұ
|
||||
#define CY_shha UC(0x04bb) // һ
|
||||
#define CY_ha_d UC(0x04b3) // ҳ
|
||||
|
||||
|
||||
// Extra
|
||||
#define CY_slr_ve UC(0x1c80) // ᲀ CYRILLIC SMALL LETTER ROUNDED VE
|
||||
#define CY_ll_de UC(0x1c81) // ᲁ CYRILLIC SMALL LETTER LONG-LEGGED DE
|
||||
#define CY_ZEMLYA UC(0xa640) // Ꙁ CYRILLIC CAPITAL LETTER ZEMLYA
|
||||
#define CY_zemlya UC(0xa641) // ꙁ CYRILLIC SMALL LETTER ZEMLYA
|
||||
#define CY_RV_DZE UC(0xa644) // Ꙅ CYRILLIC CAPITAL LETTER REVERSED DZE
|
||||
#define CY_rv_DZE UC(0xa645) // ꙅ CYRILLIC SMALL LETTER REVERSED DZE
|
||||
#define CY_slw_es UC(0x1c83) // ᲃ CYRILLIC SMALL LETTER WIDE ES
|
||||
#define CY_st_te UC(0x1c84) // ᲄ CYRILLIC SMALL LETTER TALL TE
|
||||
#define CY_3l_te UC(0x1c85) // ᲅ CYRILLIC SMALL LETTER THREE-LEGGED TE
|
||||
#define CY_thsign UC(0x1c86) // ᲆ CYRILLIC SMALL LETTER TALL HARD SIGN
|
||||
#define CY_YERUBY UC(0xa650) // Ꙑ CYRILLIC CAPITAL LETTER YERU WITH BACK YER
|
||||
#define CY_yeruby UC(0xa651) // ꙑ CYRILLIC SMALL LETTER YERU WITH BACK YER
|
||||
#define CY_RUBL UC(0x20bd) // ₽
|
||||
#define CY_NMRO UC(0x2116) // №
|
||||
|
||||
// The letters Zje and Sje are made for other letters and accent marks
|
||||
|
||||
#endif
|
|
@ -7,7 +7,18 @@
|
|||
* Jan 18th, 2014 v2.0b Initial Version
|
||||
* Nov 29th, 2015 v2.3 Added SK6812RGBW support
|
||||
*
|
||||
* License: GNU GPL v2 (see License.txt)
|
||||
* 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 "light_ws2812.h"
|
||||
|
@ -16,14 +27,128 @@
|
|||
#include <util/delay.h>
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef RGBW_BB_TWI
|
||||
|
||||
// Port for the I2C
|
||||
#define I2C_DDR DDRD
|
||||
#define I2C_PIN PIND
|
||||
#define I2C_PORT PORTD
|
||||
|
||||
// Pins to be used in the bit banging
|
||||
#define I2C_CLK 0
|
||||
#define I2C_DAT 1
|
||||
|
||||
#define I2C_DATA_HI()\
|
||||
I2C_DDR &= ~ (1 << I2C_DAT);\
|
||||
I2C_PORT |= (1 << I2C_DAT);
|
||||
#define I2C_DATA_LO()\
|
||||
I2C_DDR |= (1 << I2C_DAT);\
|
||||
I2C_PORT &= ~ (1 << I2C_DAT);
|
||||
|
||||
#define I2C_CLOCK_HI()\
|
||||
I2C_DDR &= ~ (1 << I2C_CLK);\
|
||||
I2C_PORT |= (1 << I2C_CLK);
|
||||
#define I2C_CLOCK_LO()\
|
||||
I2C_DDR |= (1 << I2C_CLK);\
|
||||
I2C_PORT &= ~ (1 << I2C_CLK);
|
||||
|
||||
#define I2C_DELAY 1
|
||||
|
||||
void I2C_WriteBit(unsigned char c)
|
||||
{
|
||||
if (c > 0)
|
||||
{
|
||||
I2C_DATA_HI();
|
||||
}
|
||||
else
|
||||
{
|
||||
I2C_DATA_LO();
|
||||
}
|
||||
|
||||
I2C_CLOCK_HI();
|
||||
_delay_us(I2C_DELAY);
|
||||
|
||||
I2C_CLOCK_LO();
|
||||
_delay_us(I2C_DELAY);
|
||||
|
||||
if (c > 0)
|
||||
{
|
||||
I2C_DATA_LO();
|
||||
}
|
||||
|
||||
_delay_us(I2C_DELAY);
|
||||
}
|
||||
|
||||
// Inits bitbanging port, must be called before using the functions below
|
||||
//
|
||||
void I2C_Init(void)
|
||||
{
|
||||
I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
|
||||
|
||||
I2C_CLOCK_HI();
|
||||
I2C_DATA_HI();
|
||||
|
||||
_delay_us(I2C_DELAY);
|
||||
}
|
||||
|
||||
// Send a START Condition
|
||||
//
|
||||
void I2C_Start(void)
|
||||
{
|
||||
// set both to high at the same time
|
||||
I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
|
||||
_delay_us(I2C_DELAY);
|
||||
|
||||
I2C_DATA_LO();
|
||||
_delay_us(I2C_DELAY);
|
||||
|
||||
I2C_CLOCK_LO();
|
||||
_delay_us(I2C_DELAY);
|
||||
}
|
||||
|
||||
// Send a STOP Condition
|
||||
//
|
||||
void I2C_Stop(void)
|
||||
{
|
||||
I2C_CLOCK_HI();
|
||||
_delay_us(I2C_DELAY);
|
||||
|
||||
I2C_DATA_HI();
|
||||
_delay_us(I2C_DELAY);
|
||||
}
|
||||
|
||||
// write a byte to the I2C slave device
|
||||
//
|
||||
unsigned char I2C_Write(unsigned char c)
|
||||
{
|
||||
for (char i = 0; i < 8; i++)
|
||||
{
|
||||
I2C_WriteBit(c & 128);
|
||||
|
||||
c <<= 1;
|
||||
}
|
||||
|
||||
|
||||
I2C_WriteBit(0);
|
||||
_delay_us(I2C_DELAY);
|
||||
_delay_us(I2C_DELAY);
|
||||
|
||||
// _delay_us(I2C_DELAY);
|
||||
//return I2C_ReadBit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// Setleds for standard RGB
|
||||
void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds)
|
||||
void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds)
|
||||
{
|
||||
// ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
|
||||
ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF));
|
||||
}
|
||||
|
||||
void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask)
|
||||
void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask)
|
||||
{
|
||||
// ws2812_DDRREG |= pinmask; // Enable DDR
|
||||
// new universal format (DDR)
|
||||
|
@ -34,14 +159,41 @@ void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pin
|
|||
}
|
||||
|
||||
// Setleds for SK6812RGBW
|
||||
void inline ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds)
|
||||
void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds)
|
||||
{
|
||||
|
||||
#ifdef RGBW_BB_TWI
|
||||
uint8_t sreg_prev, twcr_prev;
|
||||
sreg_prev=SREG;
|
||||
twcr_prev=TWCR;
|
||||
cli();
|
||||
TWCR &= ~(1<<TWEN);
|
||||
I2C_Init();
|
||||
I2C_Start();
|
||||
I2C_Write(0x84);
|
||||
uint16_t datlen = leds<<2;
|
||||
uint8_t curbyte;
|
||||
uint8_t * data = (uint8_t*)ledarray;
|
||||
while (datlen--) {
|
||||
curbyte=*data++;
|
||||
I2C_Write(curbyte);
|
||||
}
|
||||
I2C_Stop();
|
||||
SREG=sreg_prev;
|
||||
TWCR=twcr_prev;
|
||||
#endif
|
||||
|
||||
|
||||
// ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
|
||||
// new universal format (DDR)
|
||||
_SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF);
|
||||
|
||||
ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF));
|
||||
_delay_us(80);
|
||||
|
||||
|
||||
#ifndef RGBW_BB_TWI
|
||||
_delay_us(80);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ws2812_sendarray(uint8_t *data,uint16_t datlen)
|
||||
|
@ -123,7 +275,7 @@ void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
|
|||
cli();
|
||||
|
||||
while (datlen--) {
|
||||
curbyte=*data++;
|
||||
curbyte=(*data++);
|
||||
|
||||
asm volatile(
|
||||
" ldi %0,8 \n\t"
|
||||
|
|
|
@ -6,8 +6,18 @@
|
|||
*
|
||||
* Please do not change this file! All configuration is handled in "ws2812_config.h"
|
||||
*
|
||||
* License: GNU GPL v2 (see License.txt)
|
||||
+
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef LIGHT_WS2812_H_
|
||||
|
@ -16,6 +26,14 @@
|
|||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
//#include "ws2812_config.h"
|
||||
//#include "i2cmaster.h"
|
||||
|
||||
#ifdef RGBW
|
||||
#define LED_TYPE struct cRGBW
|
||||
#else
|
||||
#define LED_TYPE struct cRGB
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Structure of the LED array
|
||||
|
@ -42,9 +60,9 @@ struct cRGBW { uint8_t g; uint8_t r; uint8_t b; uint8_t w;};
|
|||
* - Wait 50<EFBFBD>s to reset the LEDs
|
||||
*/
|
||||
|
||||
void ws2812_setleds (struct cRGB *ledarray, uint16_t number_of_leds);
|
||||
void ws2812_setleds_pin (struct cRGB *ledarray, uint16_t number_of_leds,uint8_t pinmask);
|
||||
void ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t number_of_leds);
|
||||
void ws2812_setleds (LED_TYPE *ledarray, uint16_t number_of_leds);
|
||||
void ws2812_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask);
|
||||
void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
|
||||
|
||||
/*
|
||||
* Old interface / Internal functions
|
||||
|
|
341
quantum/matrix.c
341
quantum/matrix.c
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
Copyright 2012 Jun Wako
|
||||
Copyright 2014 Jack Humbert
|
||||
Copyright 2012-2017 Jun Wako, 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
|
||||
|
@ -25,37 +24,66 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "debug.h"
|
||||
#include "util.h"
|
||||
#include "matrix.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
/* Set 0 if debouncing isn't needed */
|
||||
|
||||
#ifndef DEBOUNCING_DELAY
|
||||
# define DEBOUNCING_DELAY 5
|
||||
#endif
|
||||
static uint8_t debouncing = DEBOUNCING_DELAY;
|
||||
|
||||
#if (DEBOUNCING_DELAY > 0)
|
||||
static uint16_t debouncing_time;
|
||||
static bool debouncing = false;
|
||||
#endif
|
||||
|
||||
#if (MATRIX_COLS <= 8)
|
||||
# define print_matrix_header() print("\nr/c 01234567\n")
|
||||
# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
|
||||
# define matrix_bitpop(i) bitpop(matrix[i])
|
||||
# define ROW_SHIFTER ((uint8_t)1)
|
||||
#elif (MATRIX_COLS <= 16)
|
||||
# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
|
||||
# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
|
||||
# define matrix_bitpop(i) bitpop16(matrix[i])
|
||||
# define ROW_SHIFTER ((uint16_t)1)
|
||||
#elif (MATRIX_COLS <= 32)
|
||||
# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
|
||||
# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
|
||||
# define matrix_bitpop(i) bitpop32(matrix[i])
|
||||
# define ROW_SHIFTER ((uint32_t)1)
|
||||
#endif
|
||||
|
||||
#ifdef MATRIX_MASKED
|
||||
extern const matrix_row_t matrix_mask[];
|
||||
#endif
|
||||
|
||||
#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
|
||||
static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
|
||||
static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
|
||||
#endif
|
||||
|
||||
/* matrix state(1:on, 0:off) */
|
||||
static matrix_row_t matrix[MATRIX_ROWS];
|
||||
|
||||
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
|
||||
|
||||
#if DIODE_DIRECTION == ROW2COL
|
||||
static matrix_row_t matrix_reversed[MATRIX_COLS];
|
||||
static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
|
||||
#endif
|
||||
|
||||
#if MATRIX_COLS > 16
|
||||
#define SHIFTER 1UL
|
||||
#else
|
||||
#define SHIFTER 1
|
||||
#if (DIODE_DIRECTION == COL2ROW)
|
||||
static void init_cols(void);
|
||||
static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
|
||||
static void unselect_rows(void);
|
||||
static void select_row(uint8_t row);
|
||||
static void unselect_row(uint8_t row);
|
||||
#elif (DIODE_DIRECTION == ROW2COL)
|
||||
static void init_rows(void);
|
||||
static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
|
||||
static void unselect_cols(void);
|
||||
static void unselect_col(uint8_t col);
|
||||
static void select_col(uint8_t col);
|
||||
#endif
|
||||
|
||||
static matrix_row_t read_cols(void);
|
||||
static void init_cols(void);
|
||||
static void unselect_rows(void);
|
||||
static void select_row(uint8_t row);
|
||||
|
||||
__attribute__ ((weak))
|
||||
void matrix_init_quantum(void) {
|
||||
matrix_init_kb();
|
||||
|
@ -95,7 +123,7 @@ uint8_t matrix_cols(void) {
|
|||
}
|
||||
|
||||
// void matrix_power_up(void) {
|
||||
// #if DIODE_DIRECTION == COL2ROW
|
||||
// #if (DIODE_DIRECTION == COL2ROW)
|
||||
// for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
|
||||
// /* DDRxn */
|
||||
// _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF);
|
||||
|
@ -105,7 +133,7 @@ uint8_t matrix_cols(void) {
|
|||
// /* PORTxn */
|
||||
// _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
|
||||
// }
|
||||
// #else
|
||||
// #elif (DIODE_DIRECTION == ROW2COL)
|
||||
// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
|
||||
// /* DDRxn */
|
||||
// _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
|
||||
|
@ -119,15 +147,21 @@ uint8_t matrix_cols(void) {
|
|||
// }
|
||||
|
||||
void matrix_init(void) {
|
||||
|
||||
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
|
||||
#ifdef __AVR_ATmega32U4__
|
||||
#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
|
||||
MCUCR |= _BV(JTD);
|
||||
MCUCR |= _BV(JTD);
|
||||
#endif
|
||||
|
||||
// initialize row and col
|
||||
#if (DIODE_DIRECTION == COL2ROW)
|
||||
unselect_rows();
|
||||
init_cols();
|
||||
#elif (DIODE_DIRECTION == ROW2COL)
|
||||
unselect_cols();
|
||||
init_rows();
|
||||
#endif
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
|
||||
|
@ -141,71 +175,60 @@ void matrix_init(void) {
|
|||
uint8_t matrix_scan(void)
|
||||
{
|
||||
|
||||
#if DIODE_DIRECTION == COL2ROW
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
select_row(i);
|
||||
wait_us(30); // without this wait read unstable value.
|
||||
matrix_row_t cols = read_cols();
|
||||
if (matrix_debouncing[i] != cols) {
|
||||
matrix_debouncing[i] = cols;
|
||||
if (debouncing) {
|
||||
debug("bounce!: "); debug_hex(debouncing); debug("\n");
|
||||
#if (DIODE_DIRECTION == COL2ROW)
|
||||
|
||||
// Set row, read cols
|
||||
for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
|
||||
# if (DEBOUNCING_DELAY > 0)
|
||||
bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
|
||||
|
||||
if (matrix_changed) {
|
||||
debouncing = true;
|
||||
debouncing_time = timer_read();
|
||||
}
|
||||
debouncing = DEBOUNCING_DELAY;
|
||||
}
|
||||
unselect_rows();
|
||||
|
||||
# else
|
||||
read_cols_on_row(matrix, current_row);
|
||||
# endif
|
||||
|
||||
}
|
||||
|
||||
if (debouncing) {
|
||||
if (--debouncing) {
|
||||
wait_ms(1);
|
||||
} else {
|
||||
#elif (DIODE_DIRECTION == ROW2COL)
|
||||
|
||||
// Set col, read rows
|
||||
for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
|
||||
# if (DEBOUNCING_DELAY > 0)
|
||||
bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
|
||||
if (matrix_changed) {
|
||||
debouncing = true;
|
||||
debouncing_time = timer_read();
|
||||
}
|
||||
# else
|
||||
read_rows_on_col(matrix, current_col);
|
||||
# endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
# if (DEBOUNCING_DELAY > 0)
|
||||
if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
matrix[i] = matrix_debouncing[i];
|
||||
}
|
||||
debouncing = false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (uint8_t i = 0; i < MATRIX_COLS; i++) {
|
||||
select_row(i);
|
||||
wait_us(30); // without this wait read unstable value.
|
||||
matrix_row_t rows = read_cols();
|
||||
if (matrix_reversed_debouncing[i] != rows) {
|
||||
matrix_reversed_debouncing[i] = rows;
|
||||
if (debouncing) {
|
||||
debug("bounce!: "); debug_hex(debouncing); debug("\n");
|
||||
}
|
||||
debouncing = DEBOUNCING_DELAY;
|
||||
}
|
||||
unselect_rows();
|
||||
}
|
||||
|
||||
if (debouncing) {
|
||||
if (--debouncing) {
|
||||
wait_ms(1);
|
||||
} else {
|
||||
for (uint8_t i = 0; i < MATRIX_COLS; i++) {
|
||||
matrix_reversed[i] = matrix_reversed_debouncing[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
|
||||
matrix_row_t row = 0;
|
||||
for (uint8_t x = 0; x < MATRIX_COLS; x++) {
|
||||
row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
|
||||
}
|
||||
matrix[y] = row;
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
matrix_scan_quantum();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool matrix_is_modified(void)
|
||||
{
|
||||
#if (DEBOUNCING_DELAY > 0)
|
||||
if (debouncing) return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -218,15 +241,22 @@ bool matrix_is_on(uint8_t row, uint8_t col)
|
|||
inline
|
||||
matrix_row_t matrix_get_row(uint8_t row)
|
||||
{
|
||||
// Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
|
||||
// switch blocker installed and the switch is always pressed.
|
||||
#ifdef MATRIX_MASKED
|
||||
return matrix[row] & matrix_mask[row];
|
||||
#else
|
||||
return matrix[row];
|
||||
#endif
|
||||
}
|
||||
|
||||
void matrix_print(void)
|
||||
{
|
||||
print("\nr/c 0123456789ABCDEF\n");
|
||||
print_matrix_header();
|
||||
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
||||
phex(row); print(": ");
|
||||
pbin_reverse16(matrix_get_row(row));
|
||||
print_matrix_row(row);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
|
@ -235,63 +265,148 @@ uint8_t matrix_key_count(void)
|
|||
{
|
||||
uint8_t count = 0;
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
count += bitpop16(matrix[i]);
|
||||
count += matrix_bitpop(i);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if (DIODE_DIRECTION == COL2ROW)
|
||||
|
||||
static void init_cols(void)
|
||||
{
|
||||
#if DIODE_DIRECTION == COL2ROW
|
||||
for(int x = 0; x < MATRIX_COLS; x++) {
|
||||
int pin = col_pins[x];
|
||||
#else
|
||||
for(int x = 0; x < MATRIX_ROWS; x++) {
|
||||
int pin = row_pins[x];
|
||||
#endif
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
|
||||
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
|
||||
for(uint8_t x = 0; x < MATRIX_COLS; x++) {
|
||||
uint8_t pin = col_pins[x];
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
|
||||
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
|
||||
}
|
||||
}
|
||||
|
||||
static matrix_row_t read_cols(void)
|
||||
static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
|
||||
{
|
||||
matrix_row_t result = 0;
|
||||
// Store last value of row prior to reading
|
||||
matrix_row_t last_row_value = current_matrix[current_row];
|
||||
|
||||
#if DIODE_DIRECTION == COL2ROW
|
||||
for(int x = 0; x < MATRIX_COLS; x++) {
|
||||
int pin = col_pins[x];
|
||||
#else
|
||||
for(int x = 0; x < MATRIX_ROWS; x++) {
|
||||
int pin = row_pins[x];
|
||||
#endif
|
||||
result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Clear data in matrix row
|
||||
current_matrix[current_row] = 0;
|
||||
|
||||
static void unselect_rows(void)
|
||||
{
|
||||
#if DIODE_DIRECTION == COL2ROW
|
||||
for(int x = 0; x < MATRIX_ROWS; x++) {
|
||||
int pin = row_pins[x];
|
||||
#else
|
||||
for(int x = 0; x < MATRIX_COLS; x++) {
|
||||
int pin = col_pins[x];
|
||||
#endif
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
|
||||
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
|
||||
// Select row and wait for row selecton to stabilize
|
||||
select_row(current_row);
|
||||
wait_us(30);
|
||||
|
||||
// For each col...
|
||||
for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
|
||||
|
||||
// Select the col pin to read (active low)
|
||||
uint8_t pin = col_pins[col_index];
|
||||
uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
|
||||
|
||||
// Populate the matrix row with the state of the col pin
|
||||
current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
|
||||
}
|
||||
|
||||
// Unselect row
|
||||
unselect_row(current_row);
|
||||
|
||||
return (last_row_value != current_matrix[current_row]);
|
||||
}
|
||||
|
||||
static void select_row(uint8_t row)
|
||||
{
|
||||
|
||||
#if DIODE_DIRECTION == COL2ROW
|
||||
int pin = row_pins[row];
|
||||
#else
|
||||
int pin = col_pins[row];
|
||||
#endif
|
||||
_SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF);
|
||||
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF);
|
||||
uint8_t pin = row_pins[row];
|
||||
_SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
|
||||
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
|
||||
}
|
||||
|
||||
static void unselect_row(uint8_t row)
|
||||
{
|
||||
uint8_t pin = row_pins[row];
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
|
||||
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
|
||||
}
|
||||
|
||||
static void unselect_rows(void)
|
||||
{
|
||||
for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
|
||||
uint8_t pin = row_pins[x];
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
|
||||
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
|
||||
}
|
||||
}
|
||||
|
||||
#elif (DIODE_DIRECTION == ROW2COL)
|
||||
|
||||
static void init_rows(void)
|
||||
{
|
||||
for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
|
||||
uint8_t pin = row_pins[x];
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
|
||||
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
|
||||
}
|
||||
}
|
||||
|
||||
static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
|
||||
{
|
||||
bool matrix_changed = false;
|
||||
|
||||
// Select col and wait for col selecton to stabilize
|
||||
select_col(current_col);
|
||||
wait_us(30);
|
||||
|
||||
// For each row...
|
||||
for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
|
||||
{
|
||||
|
||||
// Store last value of row prior to reading
|
||||
matrix_row_t last_row_value = current_matrix[row_index];
|
||||
|
||||
// Check row pin state
|
||||
if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
|
||||
{
|
||||
// Pin LO, set col bit
|
||||
current_matrix[row_index] |= (ROW_SHIFTER << current_col);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pin HI, clear col bit
|
||||
current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
|
||||
}
|
||||
|
||||
// Determine if the matrix changed state
|
||||
if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
|
||||
{
|
||||
matrix_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Unselect col
|
||||
unselect_col(current_col);
|
||||
|
||||
return matrix_changed;
|
||||
}
|
||||
|
||||
static void select_col(uint8_t col)
|
||||
{
|
||||
uint8_t pin = col_pins[col];
|
||||
_SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
|
||||
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
|
||||
}
|
||||
|
||||
static void unselect_col(uint8_t col)
|
||||
{
|
||||
uint8_t pin = col_pins[col];
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
|
||||
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
|
||||
}
|
||||
|
||||
static void unselect_cols(void)
|
||||
{
|
||||
for(uint8_t x = 0; x < MATRIX_COLS; x++) {
|
||||
uint8_t pin = col_pins[x];
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
|
||||
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
52
quantum/pincontrol.h
Normal file
52
quantum/pincontrol.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* Copyright 2016 Wez Furlong
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
// Some helpers for controlling gpio pins
|
||||
#include <avr/io.h>
|
||||
|
||||
enum {
|
||||
PinDirectionInput = 0,
|
||||
PinDirectionOutput = 1,
|
||||
PinLevelHigh = 1,
|
||||
PinLevelLow = 0,
|
||||
};
|
||||
|
||||
// ex: pinMode(B0, PinDirectionOutput);
|
||||
static inline void pinMode(uint8_t pin, int mode) {
|
||||
uint8_t bv = _BV(pin & 0xf);
|
||||
if (mode == PinDirectionOutput) {
|
||||
_SFR_IO8((pin >> 4) + 1) |= bv;
|
||||
} else {
|
||||
_SFR_IO8((pin >> 4) + 1) &= ~bv;
|
||||
_SFR_IO8((pin >> 4) + 2) &= ~bv;
|
||||
}
|
||||
}
|
||||
|
||||
// ex: digitalWrite(B0, PinLevelHigh);
|
||||
static inline void digitalWrite(uint8_t pin, int mode) {
|
||||
uint8_t bv = _BV(pin & 0xf);
|
||||
if (mode == PinLevelHigh) {
|
||||
_SFR_IO8((pin >> 4) + 2) |= bv;
|
||||
} else {
|
||||
_SFR_IO8((pin >> 4) + 2) &= ~bv;
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if the pin is HIGH
|
||||
// digitalRead(B0)
|
||||
static inline bool digitalRead(uint8_t pin) {
|
||||
return _SFR_IO8(pin >> 4) & _BV(pin & 0xf);
|
||||
}
|
62
quantum/process_keycode/process_audio.c
Normal file
62
quantum/process_keycode/process_audio.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "audio.h"
|
||||
#include "process_audio.h"
|
||||
|
||||
static float compute_freq_for_midi_note(uint8_t note)
|
||||
{
|
||||
// https://en.wikipedia.org/wiki/MIDI_tuning_standard
|
||||
return pow(2.0, (note - 69) / 12.0) * 440.0f;
|
||||
}
|
||||
|
||||
bool process_audio(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
if (keycode == AU_ON && record->event.pressed) {
|
||||
audio_on();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == AU_OFF && record->event.pressed) {
|
||||
audio_off();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == AU_TOG && record->event.pressed) {
|
||||
if (is_audio_on())
|
||||
{
|
||||
audio_off();
|
||||
}
|
||||
else
|
||||
{
|
||||
audio_on();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MUV_IN && record->event.pressed) {
|
||||
voice_iterate();
|
||||
music_scale_user();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MUV_DE && record->event.pressed) {
|
||||
voice_deiterate();
|
||||
music_scale_user();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void process_audio_noteon(uint8_t note) {
|
||||
play_note(compute_freq_for_midi_note(note), 0xF);
|
||||
}
|
||||
|
||||
void process_audio_noteoff(uint8_t note) {
|
||||
stop_note(compute_freq_for_midi_note(note));
|
||||
}
|
||||
|
||||
void process_audio_all_notes_off(void) {
|
||||
stop_all_notes();
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void audio_on_user() {}
|
11
quantum/process_keycode/process_audio.h
Normal file
11
quantum/process_keycode/process_audio.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef PROCESS_AUDIO_H
|
||||
#define PROCESS_AUDIO_H
|
||||
|
||||
bool process_audio(uint16_t keycode, keyrecord_t *record);
|
||||
void process_audio_noteon(uint8_t note);
|
||||
void process_audio_noteoff(uint8_t note);
|
||||
void process_audio_all_notes_off(void);
|
||||
|
||||
void audio_on_user(void);
|
||||
|
||||
#endif
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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 "process_chording.h"
|
||||
|
||||
bool keys_chord(uint8_t keys[]) {
|
||||
|
@ -57,4 +73,4 @@ bool process_chording(uint16_t keycode, keyrecord_t *record) {
|
|||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_CHORDING_H
|
||||
#define PROCESS_CHORDING_H
|
||||
|
||||
|
@ -13,4 +29,4 @@ uint8_t chord_key_down = 0;
|
|||
|
||||
bool process_chording(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
150
quantum/process_keycode/process_combo.c
Normal file
150
quantum/process_keycode/process_combo.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/* Copyright 2016 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 "process_combo.h"
|
||||
#include "print.h"
|
||||
|
||||
|
||||
#define COMBO_TIMER_ELAPSED -1
|
||||
|
||||
|
||||
__attribute__ ((weak))
|
||||
combo_t key_combos[] = {
|
||||
|
||||
};
|
||||
|
||||
__attribute__ ((weak))
|
||||
void process_combo_event(uint8_t combo_index, bool pressed) {
|
||||
|
||||
}
|
||||
|
||||
static uint8_t current_combo_index = 0;
|
||||
|
||||
static inline void send_combo(uint16_t action, bool pressed)
|
||||
{
|
||||
if (action) {
|
||||
if (pressed) {
|
||||
register_code16(action);
|
||||
} else {
|
||||
unregister_code16(action);
|
||||
}
|
||||
} else {
|
||||
process_combo_event(current_combo_index, pressed);
|
||||
}
|
||||
}
|
||||
|
||||
#define ALL_COMBO_KEYS_ARE_DOWN (((1<<count)-1) == combo->state)
|
||||
#define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state)
|
||||
#define KEY_STATE_DOWN(key) do{ combo->state |= (1<<key); } while(0)
|
||||
#define KEY_STATE_UP(key) do{ combo->state &= ~(1<<key); } while(0)
|
||||
static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint8_t index = -1;
|
||||
/* Find index of keycode and number of combo keys */
|
||||
for (const uint16_t *keys = combo->keys; ;++count) {
|
||||
uint16_t key = pgm_read_word(&keys[count]);
|
||||
if (keycode == key) index = count;
|
||||
if (COMBO_END == key) break;
|
||||
}
|
||||
|
||||
/* Return if not a combo key */
|
||||
if (-1 == (int8_t)index) return false;
|
||||
|
||||
/* The combos timer is used to signal whether the combo is active */
|
||||
bool is_combo_active = COMBO_TIMER_ELAPSED == combo->timer ? false : true;
|
||||
|
||||
if (record->event.pressed) {
|
||||
KEY_STATE_DOWN(index);
|
||||
|
||||
if (is_combo_active) {
|
||||
if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */
|
||||
send_combo(combo->keycode, true);
|
||||
combo->timer = COMBO_TIMER_ELAPSED;
|
||||
} else { /* Combo key was pressed */
|
||||
combo->timer = timer_read();
|
||||
#ifdef COMBO_ALLOW_ACTION_KEYS
|
||||
combo->prev_record = *record;
|
||||
#else
|
||||
combo->prev_key = keycode;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was released */
|
||||
send_combo(combo->keycode, false);
|
||||
}
|
||||
|
||||
if (is_combo_active) { /* Combo key was tapped */
|
||||
#ifdef COMBO_ALLOW_ACTION_KEYS
|
||||
record->event.pressed = true;
|
||||
process_action(record, store_or_get_action(record->event.pressed, record->event.key));
|
||||
record->event.pressed = false;
|
||||
process_action(record, store_or_get_action(record->event.pressed, record->event.key));
|
||||
#else
|
||||
register_code16(keycode);
|
||||
send_keyboard_report();
|
||||
unregister_code16(keycode);
|
||||
#endif
|
||||
combo->timer = 0;
|
||||
}
|
||||
|
||||
KEY_STATE_UP(index);
|
||||
}
|
||||
|
||||
if (NO_COMBO_KEYS_ARE_DOWN) {
|
||||
combo->timer = 0;
|
||||
}
|
||||
|
||||
return is_combo_active;
|
||||
}
|
||||
|
||||
bool process_combo(uint16_t keycode, keyrecord_t *record)
|
||||
{
|
||||
bool is_combo_key = false;
|
||||
|
||||
for (current_combo_index = 0; current_combo_index < COMBO_COUNT; ++current_combo_index) {
|
||||
combo_t *combo = &key_combos[current_combo_index];
|
||||
is_combo_key |= process_single_combo(combo, keycode, record);
|
||||
}
|
||||
|
||||
return !is_combo_key;
|
||||
}
|
||||
|
||||
void matrix_scan_combo(void)
|
||||
{
|
||||
for (int i = 0; i < COMBO_COUNT; ++i) {
|
||||
combo_t *combo = &key_combos[i];
|
||||
if (combo->timer &&
|
||||
combo->timer != COMBO_TIMER_ELAPSED &&
|
||||
timer_elapsed(combo->timer) > COMBO_TERM) {
|
||||
|
||||
/* This disables the combo, meaning key events for this
|
||||
* combo will be handled by the next processors in the chain
|
||||
*/
|
||||
combo->timer = COMBO_TIMER_ELAPSED;
|
||||
|
||||
#ifdef COMBO_ALLOW_ACTION_KEYS
|
||||
process_action(&combo->prev_record,
|
||||
store_or_get_action(combo->prev_record.event.pressed,
|
||||
combo->prev_record.event.key));
|
||||
#else
|
||||
unregister_code16(combo->prev_key);
|
||||
register_code16(combo->prev_key);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
59
quantum/process_keycode/process_combo.h
Normal file
59
quantum/process_keycode/process_combo.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_COMBO_H
|
||||
#define PROCESS_COMBO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "progmem.h"
|
||||
#include "quantum.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const uint16_t *keys;
|
||||
uint16_t keycode;
|
||||
#ifdef EXTRA_EXTRA_LONG_COMBOS
|
||||
uint32_t state;
|
||||
#elif EXTRA_LONG_COMBOS
|
||||
uint16_t state;
|
||||
#else
|
||||
uint8_t state;
|
||||
#endif
|
||||
uint16_t timer;
|
||||
#ifdef COMBO_ALLOW_ACTION_KEYS
|
||||
keyrecord_t prev_record;
|
||||
#else
|
||||
uint16_t prev_key;
|
||||
#endif
|
||||
} combo_t;
|
||||
|
||||
|
||||
#define COMBO(ck, ca) {.keys = &(ck)[0], .keycode = (ca)}
|
||||
#define COMBO_ACTION(ck) {.keys = &(ck)[0]}
|
||||
|
||||
#define COMBO_END 0
|
||||
#ifndef COMBO_COUNT
|
||||
#define COMBO_COUNT 0
|
||||
#endif
|
||||
#ifndef COMBO_TERM
|
||||
#define COMBO_TERM TAPPING_TERM
|
||||
#endif
|
||||
|
||||
bool process_combo(uint16_t keycode, keyrecord_t *record);
|
||||
void matrix_scan_combo(void);
|
||||
void process_combo_event(uint8_t combo_index, bool pressed);
|
||||
|
||||
#endif
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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 "process_leader.h"
|
||||
|
||||
__attribute__ ((weak))
|
||||
|
@ -35,4 +51,4 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) {
|
|||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_LEADER_H
|
||||
#define PROCESS_LEADER_H
|
||||
|
||||
|
@ -20,4 +36,4 @@ void leader_end(void);
|
|||
#define LEADER_EXTERNS() extern bool leading; extern uint16_t leader_time; extern uint16_t leader_sequence[5]; extern uint8_t leader_sequence_size
|
||||
#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,68 +1,253 @@
|
|||
/* Copyright 2016 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 "process_midi.h"
|
||||
|
||||
bool midi_activated = false;
|
||||
uint8_t midi_starting_note = 0x0C;
|
||||
int midi_offset = 7;
|
||||
#ifdef MIDI_ENABLE
|
||||
#include "midi.h"
|
||||
|
||||
bool process_midi(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == MI_ON && record->event.pressed) {
|
||||
midi_activated = true;
|
||||
#ifdef AUDIO_ENABLE
|
||||
music_scale_user();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#ifdef MIDI_BASIC
|
||||
|
||||
if (keycode == MI_OFF && record->event.pressed) {
|
||||
midi_activated = false;
|
||||
midi_send_cc(&midi_device, 0, 0x7B, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (midi_activated) {
|
||||
if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
|
||||
if (record->event.pressed) {
|
||||
midi_starting_note++; // Change key
|
||||
midi_send_cc(&midi_device, 0, 0x7B, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
|
||||
if (record->event.pressed) {
|
||||
midi_starting_note--; // Change key
|
||||
midi_send_cc(&midi_device, 0, 0x7B, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
|
||||
midi_offset++; // Change scale
|
||||
midi_send_cc(&midi_device, 0, 0x7B, 0);
|
||||
return false;
|
||||
}
|
||||
if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
|
||||
midi_offset--; // Change scale
|
||||
midi_send_cc(&midi_device, 0, 0x7B, 0);
|
||||
return false;
|
||||
}
|
||||
// basic
|
||||
// uint8_t note = (midi_starting_note + SCALE[record->event.key.col + midi_offset])+12*(MATRIX_ROWS - record->event.key.row);
|
||||
// advanced
|
||||
// uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+12*(MATRIX_ROWS - record->event.key.row);
|
||||
// guitar
|
||||
uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+5*(MATRIX_ROWS - record->event.key.row);
|
||||
// violin
|
||||
// uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+7*(MATRIX_ROWS - record->event.key.row);
|
||||
|
||||
if (record->event.pressed) {
|
||||
// midi_send_noteon(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127);
|
||||
midi_send_noteon(&midi_device, 0, note, 127);
|
||||
} else {
|
||||
// midi_send_noteoff(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127);
|
||||
midi_send_noteoff(&midi_device, 0, note, 127);
|
||||
}
|
||||
|
||||
if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
void process_midi_basic_noteon(uint8_t note)
|
||||
{
|
||||
midi_send_noteon(&midi_device, 0, note, 128);
|
||||
}
|
||||
|
||||
void process_midi_basic_noteoff(uint8_t note)
|
||||
{
|
||||
midi_send_noteoff(&midi_device, 0, note, 0);
|
||||
}
|
||||
|
||||
void process_midi_all_notes_off(void)
|
||||
{
|
||||
midi_send_cc(&midi_device, 0, 0x7B, 0);
|
||||
}
|
||||
|
||||
#endif // MIDI_BASIC
|
||||
|
||||
#ifdef MIDI_ADVANCED
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
static uint8_t tone_status[MIDI_TONE_COUNT];
|
||||
|
||||
static uint8_t midi_modulation;
|
||||
static int8_t midi_modulation_step;
|
||||
static uint16_t midi_modulation_timer;
|
||||
|
||||
inline uint8_t compute_velocity(uint8_t setting)
|
||||
{
|
||||
return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1));
|
||||
}
|
||||
|
||||
void midi_init(void)
|
||||
{
|
||||
midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN;
|
||||
midi_config.transpose = 0;
|
||||
midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN);
|
||||
midi_config.channel = 0;
|
||||
midi_config.modulation_interval = 8;
|
||||
|
||||
for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++)
|
||||
{
|
||||
tone_status[i] = MIDI_INVALID_NOTE;
|
||||
}
|
||||
|
||||
midi_modulation = 0;
|
||||
midi_modulation_step = 0;
|
||||
midi_modulation_timer = 0;
|
||||
}
|
||||
|
||||
void midi_task(void)
|
||||
{
|
||||
if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval)
|
||||
return;
|
||||
midi_modulation_timer = timer_read();
|
||||
|
||||
if (midi_modulation_step != 0)
|
||||
{
|
||||
dprintf("midi modulation %d\n", midi_modulation);
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x1, midi_modulation);
|
||||
|
||||
if (midi_modulation_step < 0 && midi_modulation < -midi_modulation_step) {
|
||||
midi_modulation = 0;
|
||||
midi_modulation_step = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
midi_modulation += midi_modulation_step;
|
||||
|
||||
if (midi_modulation > 127)
|
||||
midi_modulation = 127;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t midi_compute_note(uint16_t keycode)
|
||||
{
|
||||
return 12 * midi_config.octave + (keycode - MIDI_TONE_MIN) + midi_config.transpose;
|
||||
}
|
||||
|
||||
bool process_midi(uint16_t keycode, keyrecord_t *record)
|
||||
{
|
||||
switch (keycode) {
|
||||
case MIDI_TONE_MIN ... MIDI_TONE_MAX:
|
||||
{
|
||||
uint8_t channel = midi_config.channel;
|
||||
uint8_t tone = keycode - MIDI_TONE_MIN;
|
||||
uint8_t velocity = compute_velocity(midi_config.velocity);
|
||||
if (record->event.pressed) {
|
||||
uint8_t note = midi_compute_note(keycode);
|
||||
midi_send_noteon(&midi_device, channel, note, velocity);
|
||||
dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
|
||||
tone_status[tone] = note;
|
||||
}
|
||||
else {
|
||||
uint8_t note = tone_status[tone];
|
||||
if (note != MIDI_INVALID_NOTE)
|
||||
{
|
||||
midi_send_noteoff(&midi_device, channel, note, velocity);
|
||||
dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity);
|
||||
}
|
||||
tone_status[tone] = MIDI_INVALID_NOTE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX:
|
||||
if (record->event.pressed) {
|
||||
midi_config.octave = keycode - MIDI_OCTAVE_MIN;
|
||||
dprintf("midi octave %d\n", midi_config.octave);
|
||||
}
|
||||
return false;
|
||||
case MI_OCTD:
|
||||
if (record->event.pressed && midi_config.octave > 0) {
|
||||
midi_config.octave--;
|
||||
dprintf("midi octave %d\n", midi_config.octave);
|
||||
}
|
||||
return false;
|
||||
case MI_OCTU:
|
||||
if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) {
|
||||
midi_config.octave++;
|
||||
dprintf("midi octave %d\n", midi_config.octave);
|
||||
}
|
||||
return false;
|
||||
case MIDI_TRANSPOSE_MIN ... MIDI_TRANSPOSE_MAX:
|
||||
if (record->event.pressed) {
|
||||
midi_config.transpose = keycode - MI_TRNS_0;
|
||||
dprintf("midi transpose %d\n", midi_config.transpose);
|
||||
}
|
||||
return false;
|
||||
case MI_TRNSD:
|
||||
if (record->event.pressed && midi_config.transpose > (MIDI_TRANSPOSE_MIN - MI_TRNS_0)) {
|
||||
midi_config.transpose--;
|
||||
dprintf("midi transpose %d\n", midi_config.transpose);
|
||||
}
|
||||
return false;
|
||||
case MI_TRNSU:
|
||||
if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - MI_TRNS_0)) {
|
||||
const bool positive = midi_config.transpose > 0;
|
||||
midi_config.transpose++;
|
||||
if (positive && midi_config.transpose < 0)
|
||||
midi_config.transpose--;
|
||||
dprintf("midi transpose %d\n", midi_config.transpose);
|
||||
}
|
||||
return false;
|
||||
case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX:
|
||||
if (record->event.pressed) {
|
||||
midi_config.velocity = keycode - MIDI_VELOCITY_MIN;
|
||||
dprintf("midi velocity %d\n", midi_config.velocity);
|
||||
}
|
||||
return false;
|
||||
case MI_VELD:
|
||||
if (record->event.pressed && midi_config.velocity > 0) {
|
||||
midi_config.velocity--;
|
||||
dprintf("midi velocity %d\n", midi_config.velocity);
|
||||
}
|
||||
return false;
|
||||
case MI_VELU:
|
||||
if (record->event.pressed) {
|
||||
midi_config.velocity++;
|
||||
dprintf("midi velocity %d\n", midi_config.velocity);
|
||||
}
|
||||
return false;
|
||||
case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX:
|
||||
if (record->event.pressed) {
|
||||
midi_config.channel = keycode - MIDI_CHANNEL_MIN;
|
||||
dprintf("midi channel %d\n", midi_config.channel);
|
||||
}
|
||||
return false;
|
||||
case MI_CHD:
|
||||
if (record->event.pressed) {
|
||||
midi_config.channel--;
|
||||
dprintf("midi channel %d\n", midi_config.channel);
|
||||
}
|
||||
return false;
|
||||
case MI_CHU:
|
||||
if (record->event.pressed) {
|
||||
midi_config.channel++;
|
||||
dprintf("midi channel %d\n", midi_config.channel);
|
||||
}
|
||||
return false;
|
||||
case MI_ALLOFF:
|
||||
if (record->event.pressed) {
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0);
|
||||
dprintf("midi all notes off\n");
|
||||
}
|
||||
return false;
|
||||
case MI_SUS:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x40, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi sustain %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_PORT:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x41, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi portamento %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_SOST:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x42, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi sostenuto %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_SOFT:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi soft %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_LEG:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi legato %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_MOD:
|
||||
midi_modulation_step = record->event.pressed ? 1 : -1;
|
||||
return false;
|
||||
case MI_MODSD:
|
||||
if (record->event.pressed) {
|
||||
midi_config.modulation_interval++;
|
||||
// prevent overflow
|
||||
if (midi_config.modulation_interval == 0)
|
||||
midi_config.modulation_interval--;
|
||||
dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
|
||||
}
|
||||
return false;
|
||||
case MI_MODSU:
|
||||
if (record->event.pressed && midi_config.modulation_interval > 0) {
|
||||
midi_config.modulation_interval--;
|
||||
dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // MIDI_ADVANCED
|
||||
|
||||
#endif // MIDI_ENABLE
|
||||
|
|
|
@ -1,207 +1,56 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_MIDI_H
|
||||
#define PROCESS_MIDI_H
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
|
||||
#ifdef MIDI_BASIC
|
||||
void process_midi_basic_noteon(uint8_t note);
|
||||
void process_midi_basic_noteoff(uint8_t note);
|
||||
void process_midi_all_notes_off(void);
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ADVANCED
|
||||
typedef union {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint8_t octave :4;
|
||||
int8_t transpose :4;
|
||||
uint8_t velocity :4;
|
||||
uint8_t channel :4;
|
||||
uint8_t modulation_interval :4;
|
||||
};
|
||||
} midi_config_t;
|
||||
|
||||
midi_config_t midi_config;
|
||||
|
||||
void midi_init(void);
|
||||
void midi_task(void);
|
||||
bool process_midi(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
#define MIDI(n) ((n) | 0x6000)
|
||||
#define MIDI12 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000
|
||||
#define MIDI_INVALID_NOTE 0xFF
|
||||
#define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1)
|
||||
|
||||
#define CHNL(note, channel) (note + (channel << 8))
|
||||
uint8_t midi_compute_note(uint16_t keycode);
|
||||
#endif // MIDI_ADVANCED
|
||||
|
||||
#define SCALE (int8_t []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
|
||||
0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
|
||||
0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
|
||||
0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
|
||||
0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
|
||||
#endif // MIDI_ENABLE
|
||||
|
||||
#define N_CN1 (0x600C + (12 * -1) + 0 )
|
||||
#define N_CN1S (0x600C + (12 * -1) + 1 )
|
||||
#define N_DN1F (0x600C + (12 * -1) + 1 )
|
||||
#define N_DN1 (0x600C + (12 * -1) + 2 )
|
||||
#define N_DN1S (0x600C + (12 * -1) + 3 )
|
||||
#define N_EN1F (0x600C + (12 * -1) + 3 )
|
||||
#define N_EN1 (0x600C + (12 * -1) + 4 )
|
||||
#define N_FN1 (0x600C + (12 * -1) + 5 )
|
||||
#define N_FN1S (0x600C + (12 * -1) + 6 )
|
||||
#define N_GN1F (0x600C + (12 * -1) + 6 )
|
||||
#define N_GN1 (0x600C + (12 * -1) + 7 )
|
||||
#define N_GN1S (0x600C + (12 * -1) + 8 )
|
||||
#define N_AN1F (0x600C + (12 * -1) + 8 )
|
||||
#define N_AN1 (0x600C + (12 * -1) + 9 )
|
||||
#define N_AN1S (0x600C + (12 * -1) + 10)
|
||||
#define N_BN1F (0x600C + (12 * -1) + 10)
|
||||
#define N_BN1 (0x600C + (12 * -1) + 11)
|
||||
#define N_C0 (0x600C + (12 * 0) + 0 )
|
||||
#define N_C0S (0x600C + (12 * 0) + 1 )
|
||||
#define N_D0F (0x600C + (12 * 0) + 1 )
|
||||
#define N_D0 (0x600C + (12 * 0) + 2 )
|
||||
#define N_D0S (0x600C + (12 * 0) + 3 )
|
||||
#define N_E0F (0x600C + (12 * 0) + 3 )
|
||||
#define N_E0 (0x600C + (12 * 0) + 4 )
|
||||
#define N_F0 (0x600C + (12 * 0) + 5 )
|
||||
#define N_F0S (0x600C + (12 * 0) + 6 )
|
||||
#define N_G0F (0x600C + (12 * 0) + 6 )
|
||||
#define N_G0 (0x600C + (12 * 0) + 7 )
|
||||
#define N_G0S (0x600C + (12 * 0) + 8 )
|
||||
#define N_A0F (0x600C + (12 * 0) + 8 )
|
||||
#define N_A0 (0x600C + (12 * 0) + 9 )
|
||||
#define N_A0S (0x600C + (12 * 0) + 10)
|
||||
#define N_B0F (0x600C + (12 * 0) + 10)
|
||||
#define N_B0 (0x600C + (12 * 0) + 11)
|
||||
#define N_C1 (0x600C + (12 * 1) + 0 )
|
||||
#define N_C1S (0x600C + (12 * 1) + 1 )
|
||||
#define N_D1F (0x600C + (12 * 1) + 1 )
|
||||
#define N_D1 (0x600C + (12 * 1) + 2 )
|
||||
#define N_D1S (0x600C + (12 * 1) + 3 )
|
||||
#define N_E1F (0x600C + (12 * 1) + 3 )
|
||||
#define N_E1 (0x600C + (12 * 1) + 4 )
|
||||
#define N_F1 (0x600C + (12 * 1) + 5 )
|
||||
#define N_F1S (0x600C + (12 * 1) + 6 )
|
||||
#define N_G1F (0x600C + (12 * 1) + 6 )
|
||||
#define N_G1 (0x600C + (12 * 1) + 7 )
|
||||
#define N_G1S (0x600C + (12 * 1) + 8 )
|
||||
#define N_A1F (0x600C + (12 * 1) + 8 )
|
||||
#define N_A1 (0x600C + (12 * 1) + 9 )
|
||||
#define N_A1S (0x600C + (12 * 1) + 10)
|
||||
#define N_B1F (0x600C + (12 * 1) + 10)
|
||||
#define N_B1 (0x600C + (12 * 1) + 11)
|
||||
#define N_C2 (0x600C + (12 * 2) + 0 )
|
||||
#define N_C2S (0x600C + (12 * 2) + 1 )
|
||||
#define N_D2F (0x600C + (12 * 2) + 1 )
|
||||
#define N_D2 (0x600C + (12 * 2) + 2 )
|
||||
#define N_D2S (0x600C + (12 * 2) + 3 )
|
||||
#define N_E2F (0x600C + (12 * 2) + 3 )
|
||||
#define N_E2 (0x600C + (12 * 2) + 4 )
|
||||
#define N_F2 (0x600C + (12 * 2) + 5 )
|
||||
#define N_F2S (0x600C + (12 * 2) + 6 )
|
||||
#define N_G2F (0x600C + (12 * 2) + 6 )
|
||||
#define N_G2 (0x600C + (12 * 2) + 7 )
|
||||
#define N_G2S (0x600C + (12 * 2) + 8 )
|
||||
#define N_A2F (0x600C + (12 * 2) + 8 )
|
||||
#define N_A2 (0x600C + (12 * 2) + 9 )
|
||||
#define N_A2S (0x600C + (12 * 2) + 10)
|
||||
#define N_B2F (0x600C + (12 * 2) + 10)
|
||||
#define N_B2 (0x600C + (12 * 2) + 11)
|
||||
#define N_C3 (0x600C + (12 * 3) + 0 )
|
||||
#define N_C3S (0x600C + (12 * 3) + 1 )
|
||||
#define N_D3F (0x600C + (12 * 3) + 1 )
|
||||
#define N_D3 (0x600C + (12 * 3) + 2 )
|
||||
#define N_D3S (0x600C + (12 * 3) + 3 )
|
||||
#define N_E3F (0x600C + (12 * 3) + 3 )
|
||||
#define N_E3 (0x600C + (12 * 3) + 4 )
|
||||
#define N_F3 (0x600C + (12 * 3) + 5 )
|
||||
#define N_F3S (0x600C + (12 * 3) + 6 )
|
||||
#define N_G3F (0x600C + (12 * 3) + 6 )
|
||||
#define N_G3 (0x600C + (12 * 3) + 7 )
|
||||
#define N_G3S (0x600C + (12 * 3) + 8 )
|
||||
#define N_A3F (0x600C + (12 * 3) + 8 )
|
||||
#define N_A3 (0x600C + (12 * 3) + 9 )
|
||||
#define N_A3S (0x600C + (12 * 3) + 10)
|
||||
#define N_B3F (0x600C + (12 * 3) + 10)
|
||||
#define N_B3 (0x600C + (12 * 3) + 11)
|
||||
#define N_C4 (0x600C + (12 * 4) + 0 )
|
||||
#define N_C4S (0x600C + (12 * 4) + 1 )
|
||||
#define N_D4F (0x600C + (12 * 4) + 1 )
|
||||
#define N_D4 (0x600C + (12 * 4) + 2 )
|
||||
#define N_D4S (0x600C + (12 * 4) + 3 )
|
||||
#define N_E4F (0x600C + (12 * 4) + 3 )
|
||||
#define N_E4 (0x600C + (12 * 4) + 4 )
|
||||
#define N_F4 (0x600C + (12 * 4) + 5 )
|
||||
#define N_F4S (0x600C + (12 * 4) + 6 )
|
||||
#define N_G4F (0x600C + (12 * 4) + 6 )
|
||||
#define N_G4 (0x600C + (12 * 4) + 7 )
|
||||
#define N_G4S (0x600C + (12 * 4) + 8 )
|
||||
#define N_A4F (0x600C + (12 * 4) + 8 )
|
||||
#define N_A4 (0x600C + (12 * 4) + 9 )
|
||||
#define N_A4S (0x600C + (12 * 4) + 10)
|
||||
#define N_B4F (0x600C + (12 * 4) + 10)
|
||||
#define N_B4 (0x600C + (12 * 4) + 11)
|
||||
#define N_C5 (0x600C + (12 * 5) + 0 )
|
||||
#define N_C5S (0x600C + (12 * 5) + 1 )
|
||||
#define N_D5F (0x600C + (12 * 5) + 1 )
|
||||
#define N_D5 (0x600C + (12 * 5) + 2 )
|
||||
#define N_D5S (0x600C + (12 * 5) + 3 )
|
||||
#define N_E5F (0x600C + (12 * 5) + 3 )
|
||||
#define N_E5 (0x600C + (12 * 5) + 4 )
|
||||
#define N_F5 (0x600C + (12 * 5) + 5 )
|
||||
#define N_F5S (0x600C + (12 * 5) + 6 )
|
||||
#define N_G5F (0x600C + (12 * 5) + 6 )
|
||||
#define N_G5 (0x600C + (12 * 5) + 7 )
|
||||
#define N_G5S (0x600C + (12 * 5) + 8 )
|
||||
#define N_A5F (0x600C + (12 * 5) + 8 )
|
||||
#define N_A5 (0x600C + (12 * 5) + 9 )
|
||||
#define N_A5S (0x600C + (12 * 5) + 10)
|
||||
#define N_B5F (0x600C + (12 * 5) + 10)
|
||||
#define N_B5 (0x600C + (12 * 5) + 11)
|
||||
#define N_C6 (0x600C + (12 * 6) + 0 )
|
||||
#define N_C6S (0x600C + (12 * 6) + 1 )
|
||||
#define N_D6F (0x600C + (12 * 6) + 1 )
|
||||
#define N_D6 (0x600C + (12 * 6) + 2 )
|
||||
#define N_D6S (0x600C + (12 * 6) + 3 )
|
||||
#define N_E6F (0x600C + (12 * 6) + 3 )
|
||||
#define N_E6 (0x600C + (12 * 6) + 4 )
|
||||
#define N_F6 (0x600C + (12 * 6) + 5 )
|
||||
#define N_F6S (0x600C + (12 * 6) + 6 )
|
||||
#define N_G6F (0x600C + (12 * 6) + 6 )
|
||||
#define N_G6 (0x600C + (12 * 6) + 7 )
|
||||
#define N_G6S (0x600C + (12 * 6) + 8 )
|
||||
#define N_A6F (0x600C + (12 * 6) + 8 )
|
||||
#define N_A6 (0x600C + (12 * 6) + 9 )
|
||||
#define N_A6S (0x600C + (12 * 6) + 10)
|
||||
#define N_B6F (0x600C + (12 * 6) + 10)
|
||||
#define N_B6 (0x600C + (12 * 6) + 11)
|
||||
#define N_C7 (0x600C + (12 * 7) + 0 )
|
||||
#define N_C7S (0x600C + (12 * 7) + 1 )
|
||||
#define N_D7F (0x600C + (12 * 7) + 1 )
|
||||
#define N_D7 (0x600C + (12 * 7) + 2 )
|
||||
#define N_D7S (0x600C + (12 * 7) + 3 )
|
||||
#define N_E7F (0x600C + (12 * 7) + 3 )
|
||||
#define N_E7 (0x600C + (12 * 7) + 4 )
|
||||
#define N_F7 (0x600C + (12 * 7) + 5 )
|
||||
#define N_F7S (0x600C + (12 * 7) + 6 )
|
||||
#define N_G7F (0x600C + (12 * 7) + 6 )
|
||||
#define N_G7 (0x600C + (12 * 7) + 7 )
|
||||
#define N_G7S (0x600C + (12 * 7) + 8 )
|
||||
#define N_A7F (0x600C + (12 * 7) + 8 )
|
||||
#define N_A7 (0x600C + (12 * 7) + 9 )
|
||||
#define N_A7S (0x600C + (12 * 7) + 10)
|
||||
#define N_B7F (0x600C + (12 * 7) + 10)
|
||||
#define N_B7 (0x600C + (12 * 7) + 11)
|
||||
#define N_C8 (0x600C + (12 * 8) + 0 )
|
||||
#define N_C8S (0x600C + (12 * 8) + 1 )
|
||||
#define N_D8F (0x600C + (12 * 8) + 1 )
|
||||
#define N_D8 (0x600C + (12 * 8) + 2 )
|
||||
#define N_D8S (0x600C + (12 * 8) + 3 )
|
||||
#define N_E8F (0x600C + (12 * 8) + 3 )
|
||||
#define N_E8 (0x600C + (12 * 8) + 4 )
|
||||
#define N_F8 (0x600C + (12 * 8) + 5 )
|
||||
#define N_F8S (0x600C + (12 * 8) + 6 )
|
||||
#define N_G8F (0x600C + (12 * 8) + 6 )
|
||||
#define N_G8 (0x600C + (12 * 8) + 7 )
|
||||
#define N_G8S (0x600C + (12 * 8) + 8 )
|
||||
#define N_A8F (0x600C + (12 * 8) + 8 )
|
||||
#define N_A8 (0x600C + (12 * 8) + 9 )
|
||||
#define N_A8S (0x600C + (12 * 8) + 10)
|
||||
#define N_B8F (0x600C + (12 * 8) + 10)
|
||||
#define N_B8 (0x600C + (12 * 8) + 11)
|
||||
#define N_C8 (0x600C + (12 * 8) + 0 )
|
||||
#define N_C8S (0x600C + (12 * 8) + 1 )
|
||||
#define N_D8F (0x600C + (12 * 8) + 1 )
|
||||
#define N_D8 (0x600C + (12 * 8) + 2 )
|
||||
#define N_D8S (0x600C + (12 * 8) + 3 )
|
||||
#define N_E8F (0x600C + (12 * 8) + 3 )
|
||||
#define N_E8 (0x600C + (12 * 8) + 4 )
|
||||
#define N_F8 (0x600C + (12 * 8) + 5 )
|
||||
#define N_F8S (0x600C + (12 * 8) + 6 )
|
||||
#define N_G8F (0x600C + (12 * 8) + 6 )
|
||||
#define N_G8 (0x600C + (12 * 8) + 7 )
|
||||
#define N_G8S (0x600C + (12 * 8) + 8 )
|
||||
#define N_A8F (0x600C + (12 * 8) + 8 )
|
||||
#define N_A8 (0x600C + (12 * 8) + 9 )
|
||||
#define N_A8S (0x600C + (12 * 8) + 10)
|
||||
#define N_B8F (0x600C + (12 * 8) + 10)
|
||||
#define N_B8 (0x600C + (12 * 8) + 11)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,44 +1,73 @@
|
|||
/* Copyright 2016 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 "process_music.h"
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
#include "process_audio.h"
|
||||
#endif
|
||||
#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
|
||||
#include "process_midi.h"
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
||||
|
||||
bool music_activated = false;
|
||||
uint8_t starting_note = 0x0C;
|
||||
int offset = 7;
|
||||
uint8_t music_starting_note = 0x0C;
|
||||
int music_offset = 7;
|
||||
|
||||
// music sequencer
|
||||
static bool music_sequence_recording = false;
|
||||
static bool music_sequence_recorded = false;
|
||||
static bool music_sequence_playing = false;
|
||||
static float music_sequence[16] = {0};
|
||||
static uint8_t music_sequence[16] = {0};
|
||||
static uint8_t music_sequence_count = 0;
|
||||
static uint8_t music_sequence_position = 0;
|
||||
|
||||
static uint16_t music_sequence_timer = 0;
|
||||
static uint16_t music_sequence_interval = 100;
|
||||
|
||||
static void music_noteon(uint8_t note) {
|
||||
#ifdef AUDIO_ENABLE
|
||||
process_audio_noteon(note);
|
||||
#endif
|
||||
#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
|
||||
process_midi_basic_noteon(note);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void music_noteoff(uint8_t note) {
|
||||
#ifdef AUDIO_ENABLE
|
||||
process_audio_noteoff(note);
|
||||
#endif
|
||||
#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
|
||||
process_midi_basic_noteoff(note);
|
||||
#endif
|
||||
}
|
||||
|
||||
void music_all_notes_off(void) {
|
||||
#ifdef AUDIO_ENABLE
|
||||
process_audio_all_notes_off();
|
||||
#endif
|
||||
#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
|
||||
process_midi_all_notes_off();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool process_music(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
if (keycode == AU_ON && record->event.pressed) {
|
||||
audio_on();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == AU_OFF && record->event.pressed) {
|
||||
audio_off();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == AU_TOG && record->event.pressed) {
|
||||
if (is_audio_on())
|
||||
{
|
||||
audio_off();
|
||||
}
|
||||
else
|
||||
{
|
||||
audio_on();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MU_ON && record->event.pressed) {
|
||||
music_on();
|
||||
return false;
|
||||
|
@ -61,22 +90,10 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MUV_IN && record->event.pressed) {
|
||||
voice_iterate();
|
||||
music_scale_user();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MUV_DE && record->event.pressed) {
|
||||
voice_deiterate();
|
||||
music_scale_user();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (music_activated) {
|
||||
|
||||
if (keycode == KC_LCTL && record->event.pressed) { // Start recording
|
||||
stop_all_notes();
|
||||
music_all_notes_off();
|
||||
music_sequence_recording = true;
|
||||
music_sequence_recorded = false;
|
||||
music_sequence_playing = false;
|
||||
|
@ -85,7 +102,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
|
|||
}
|
||||
|
||||
if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing
|
||||
stop_all_notes();
|
||||
music_all_notes_off();
|
||||
if (music_sequence_recording) { // was recording
|
||||
music_sequence_recorded = true;
|
||||
}
|
||||
|
@ -95,7 +112,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
|
|||
}
|
||||
|
||||
if (keycode == KC_LGUI && record->event.pressed && music_sequence_recorded) { // Start playing
|
||||
stop_all_notes();
|
||||
music_all_notes_off();
|
||||
music_sequence_recording = false;
|
||||
music_sequence_playing = true;
|
||||
music_sequence_position = 0;
|
||||
|
@ -115,21 +132,33 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
|
|||
return false;
|
||||
}
|
||||
|
||||
float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row));
|
||||
#define MUSIC_MODE_GUITAR
|
||||
|
||||
#ifdef MUSIC_MODE_CHROMATIC
|
||||
uint8_t note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row);
|
||||
#elif defined(MUSIC_MODE_GUITAR)
|
||||
uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row);
|
||||
#elif defined(MUSIC_MODE_VIOLIN)
|
||||
uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row);
|
||||
#else
|
||||
uint8_t note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row);
|
||||
#endif
|
||||
|
||||
if (record->event.pressed) {
|
||||
play_note(freq, 0xF);
|
||||
music_noteon(note);
|
||||
if (music_sequence_recording) {
|
||||
music_sequence[music_sequence_count] = freq;
|
||||
music_sequence[music_sequence_count] = note;
|
||||
music_sequence_count++;
|
||||
}
|
||||
} else {
|
||||
stop_note(freq);
|
||||
music_noteoff(note);
|
||||
}
|
||||
|
||||
if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_music_on(void) {
|
||||
|
@ -151,26 +180,26 @@ void music_on(void) {
|
|||
|
||||
void music_off(void) {
|
||||
music_activated = 0;
|
||||
stop_all_notes();
|
||||
music_all_notes_off();
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((weak))
|
||||
void music_on_user() {}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void audio_on_user() {}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void music_scale_user() {}
|
||||
|
||||
void matrix_scan_music(void) {
|
||||
if (music_sequence_playing) {
|
||||
if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
|
||||
music_sequence_timer = timer_read();
|
||||
stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]);
|
||||
play_note(music_sequence[music_sequence_position], 0xF);
|
||||
uint8_t prev_note = music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)];
|
||||
uint8_t next_note = music_sequence[music_sequence_position];
|
||||
music_noteoff(prev_note);
|
||||
music_noteon(next_note);
|
||||
music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void music_on_user() {}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void music_scale_user() {}
|
||||
|
||||
#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
|
@ -1,8 +1,26 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_MUSIC_H
|
||||
#define PROCESS_MUSIC_H
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
||||
|
||||
bool process_music(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
bool is_music_on(void);
|
||||
|
@ -10,9 +28,9 @@ void music_toggle(void);
|
|||
void music_on(void);
|
||||
void music_off(void);
|
||||
|
||||
void audio_on_user(void);
|
||||
void music_on_user(void);
|
||||
void music_scale_user(void);
|
||||
void music_all_notes_off(void);
|
||||
|
||||
void matrix_scan_music(void);
|
||||
|
||||
|
@ -24,4 +42,6 @@ void matrix_scan_music(void);
|
|||
0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
||||
|
||||
#endif
|
||||
|
|
270
quantum/process_keycode/process_printer.c
Normal file
270
quantum/process_keycode/process_printer.c
Normal file
|
@ -0,0 +1,270 @@
|
|||
/* Copyright 2016 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 "process_printer.h"
|
||||
#include "action_util.h"
|
||||
|
||||
bool printing_enabled = false;
|
||||
uint8_t character_shift = 0;
|
||||
|
||||
void enabled_printing() {
|
||||
printing_enabled = true;
|
||||
serial_init();
|
||||
}
|
||||
|
||||
void disable_printing() {
|
||||
printing_enabled = false;
|
||||
}
|
||||
|
||||
uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
|
||||
|
||||
// uint8_t keycode_to_ascii[0xFF][2];
|
||||
|
||||
// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
|
||||
|
||||
void print_char(char c) {
|
||||
USB_Disable();
|
||||
serial_send(c);
|
||||
USB_Init();
|
||||
}
|
||||
|
||||
void print_box_string(uint8_t text[]) {
|
||||
uint8_t len = strlen(text);
|
||||
uint8_t out[len * 3 + 8];
|
||||
out[0] = 0xDA;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
out[i+1] = 0xC4;
|
||||
}
|
||||
out[len + 1] = 0xBF;
|
||||
out[len + 2] = '\n';
|
||||
|
||||
out[len + 3] = 0xB3;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
out[len + 4 + i] = text[i];
|
||||
}
|
||||
out[len * 2 + 4] = 0xB3;
|
||||
out[len * 2 + 5] = '\n';
|
||||
|
||||
|
||||
out[len * 2 + 6] = 0xC0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
out[len * 2 + 7 + i] = 0xC4;
|
||||
}
|
||||
out[len * 3 + 7] = 0xD9;
|
||||
out[len * 3 + 8] = '\n';
|
||||
|
||||
print_string(out);
|
||||
}
|
||||
|
||||
void print_string(char c[]) {
|
||||
for(uint8_t i = 0; i < strlen(c); i++)
|
||||
print_char(c[i]);
|
||||
}
|
||||
|
||||
bool process_printer(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == PRINT_ON) {
|
||||
enabled_printing();
|
||||
return false;
|
||||
}
|
||||
if (keycode == PRINT_OFF) {
|
||||
disable_printing();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (printing_enabled) {
|
||||
switch(keycode) {
|
||||
case KC_EXLM ... KC_RPRN:
|
||||
case KC_UNDS:
|
||||
case KC_PLUS:
|
||||
case KC_LCBR:
|
||||
case KC_RCBR:
|
||||
case KC_PIPE:
|
||||
case KC_TILD:
|
||||
keycode &= 0xFF;
|
||||
case KC_LSFT:
|
||||
case KC_RSFT:
|
||||
if (record->event.pressed) {
|
||||
character_shift++;
|
||||
} else {
|
||||
character_shift--;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(keycode) {
|
||||
case KC_F1:
|
||||
if (record->event.pressed) {
|
||||
print_box_string("This is a line of text!");
|
||||
}
|
||||
return false;
|
||||
case KC_ESC:
|
||||
if (record->event.pressed) {
|
||||
print_char(0x1B);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_SPC:
|
||||
if (record->event.pressed) {
|
||||
print_char(0x20);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_A ... KC_Z:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x41 + (keycode - KC_A));
|
||||
} else {
|
||||
print_char(0x61 + (keycode - KC_A));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_1 ... KC_0:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(shifted_numbers[keycode - KC_1]);
|
||||
} else {
|
||||
print_char(0x30 + ((keycode - KC_1 + 1) % 10));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_ENT:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x0C);
|
||||
} else {
|
||||
print_char(0x0A);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_BSPC:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x18);
|
||||
} else {
|
||||
print_char(0x1A);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_DOT:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3E);
|
||||
} else {
|
||||
print_char(0x2E);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_COMM:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3C);
|
||||
} else {
|
||||
print_char(0x2C);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_SLSH:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3F);
|
||||
} else {
|
||||
print_char(0x2F);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_QUOT:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x22);
|
||||
} else {
|
||||
print_char(0x27);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_GRV:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7E);
|
||||
} else {
|
||||
print_char(0x60);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_MINS:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x5F);
|
||||
} else {
|
||||
print_char(0x2D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_EQL:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x2B);
|
||||
} else {
|
||||
print_char(0x3D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_LBRC:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7B);
|
||||
} else {
|
||||
print_char(0x5B);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_RBRC:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7D);
|
||||
} else {
|
||||
print_char(0x5D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_BSLS:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7C);
|
||||
} else {
|
||||
print_char(0x5C);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
24
quantum/process_keycode/process_printer.h
Normal file
24
quantum/process_keycode/process_printer.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_PRINTER_H
|
||||
#define PROCESS_PRINTER_H
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
#include "protocol/serial.h"
|
||||
|
||||
#endif
|
276
quantum/process_keycode/process_printer_bb.c
Normal file
276
quantum/process_keycode/process_printer_bb.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
/* Copyright 2016 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 "process_printer.h"
|
||||
#include "action_util.h"
|
||||
|
||||
bool printing_enabled = false;
|
||||
uint8_t character_shift = 0;
|
||||
|
||||
#define SERIAL_PIN_DDR DDRD
|
||||
#define SERIAL_PIN_PORT PORTD
|
||||
#define SERIAL_PIN_MASK _BV(PD3)
|
||||
#define SERIAL_DELAY 52
|
||||
|
||||
inline static
|
||||
void serial_delay(void) {
|
||||
_delay_us(SERIAL_DELAY);
|
||||
}
|
||||
|
||||
inline static
|
||||
void serial_high(void) {
|
||||
SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
|
||||
}
|
||||
|
||||
inline static
|
||||
void serial_low(void) {
|
||||
SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
|
||||
}
|
||||
|
||||
inline static
|
||||
void serial_output(void) {
|
||||
SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
|
||||
}
|
||||
|
||||
|
||||
void enabled_printing() {
|
||||
printing_enabled = true;
|
||||
serial_output();
|
||||
serial_high();
|
||||
}
|
||||
|
||||
void disable_printing() {
|
||||
printing_enabled = false;
|
||||
}
|
||||
|
||||
uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
|
||||
|
||||
// uint8_t keycode_to_ascii[0xFF][2];
|
||||
|
||||
// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
|
||||
|
||||
void print_char(char c) {
|
||||
uint8_t b = 8;
|
||||
serial_output();
|
||||
while( b-- ) {
|
||||
if(c & (1 << b)) {
|
||||
serial_high();
|
||||
} else {
|
||||
serial_low();
|
||||
}
|
||||
serial_delay();
|
||||
}
|
||||
}
|
||||
|
||||
void print_string(char c[]) {
|
||||
for(uint8_t i = 0; i < strlen(c); i++)
|
||||
print_char(c[i]);
|
||||
}
|
||||
|
||||
bool process_printer(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == PRINT_ON) {
|
||||
enabled_printing();
|
||||
return false;
|
||||
}
|
||||
if (keycode == PRINT_OFF) {
|
||||
disable_printing();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (printing_enabled) {
|
||||
switch(keycode) {
|
||||
case KC_EXLM ... KC_RPRN:
|
||||
case KC_UNDS:
|
||||
case KC_PLUS:
|
||||
case KC_LCBR:
|
||||
case KC_RCBR:
|
||||
case KC_PIPE:
|
||||
case KC_TILD:
|
||||
keycode &= 0xFF;
|
||||
case KC_LSFT:
|
||||
case KC_RSFT:
|
||||
if (record->event.pressed) {
|
||||
character_shift++;
|
||||
} else {
|
||||
character_shift--;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(keycode) {
|
||||
case KC_F1:
|
||||
if (record->event.pressed) {
|
||||
print_string("This is a line of text!\n\n\n");
|
||||
}
|
||||
return false;
|
||||
case KC_ESC:
|
||||
if (record->event.pressed) {
|
||||
print_char(0x1B);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_SPC:
|
||||
if (record->event.pressed) {
|
||||
print_char(0x20);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_A ... KC_Z:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x41 + (keycode - KC_A));
|
||||
} else {
|
||||
print_char(0x61 + (keycode - KC_A));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_1 ... KC_0:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(shifted_numbers[keycode - KC_1]);
|
||||
} else {
|
||||
print_char(0x30 + ((keycode - KC_1 + 1) % 10));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_ENT:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x0C);
|
||||
} else {
|
||||
print_char(0x0A);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_BSPC:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x18);
|
||||
} else {
|
||||
print_char(0x1A);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_DOT:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3E);
|
||||
} else {
|
||||
print_char(0x2E);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_COMM:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3C);
|
||||
} else {
|
||||
print_char(0x2C);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_SLSH:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3F);
|
||||
} else {
|
||||
print_char(0x2F);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_QUOT:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x22);
|
||||
} else {
|
||||
print_char(0x27);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_GRV:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7E);
|
||||
} else {
|
||||
print_char(0x60);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_MINS:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x5F);
|
||||
} else {
|
||||
print_char(0x2D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_EQL:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x2B);
|
||||
} else {
|
||||
print_char(0x3D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_LBRC:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7B);
|
||||
} else {
|
||||
print_char(0x5B);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_RBRC:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7D);
|
||||
} else {
|
||||
print_char(0x5D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_BSLS:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7C);
|
||||
} else {
|
||||
print_char(0x5C);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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"
|
||||
#include "action_tapping.h"
|
||||
|
||||
|
@ -43,12 +58,16 @@ static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_acti
|
|||
if (action->state.finished)
|
||||
return;
|
||||
action->state.finished = true;
|
||||
add_mods(action->state.oneshot_mods);
|
||||
send_keyboard_report();
|
||||
_process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
|
||||
}
|
||||
|
||||
static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
|
||||
{
|
||||
_process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
|
||||
del_mods(action->state.oneshot_mods);
|
||||
send_keyboard_report();
|
||||
}
|
||||
|
||||
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
|
@ -70,6 +89,7 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
|||
action->state.keycode = keycode;
|
||||
action->state.count++;
|
||||
action->state.timer = timer_read();
|
||||
action->state.oneshot_mods = get_oneshot_mods();
|
||||
process_tap_dance_action_on_each_tap (action);
|
||||
|
||||
if (last_td && last_td != keycode) {
|
||||
|
@ -109,7 +129,7 @@ void matrix_scan_tap_dance () {
|
|||
if (highest_td == -1)
|
||||
return;
|
||||
|
||||
for (int i = 0; i <= highest_td; i++) {
|
||||
for (int i = 0; i <= highest_td; i++) {
|
||||
qk_tap_dance_action_t *action = &tap_dance_actions[i];
|
||||
|
||||
if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
#ifndef PROCESS_TAP_DANCE_H
|
||||
#define PROCESS_TAP_DANCE_H
|
||||
|
||||
|
@ -9,6 +24,7 @@
|
|||
typedef struct
|
||||
{
|
||||
uint8_t count;
|
||||
uint8_t oneshot_mods;
|
||||
uint16_t keycode;
|
||||
uint16_t timer;
|
||||
bool interrupted;
|
||||
|
|
149
quantum/process_keycode/process_ucis.c
Normal file
149
quantum/process_keycode/process_ucis.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/* Copyright 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 "process_ucis.h"
|
||||
|
||||
qk_ucis_state_t qk_ucis_state;
|
||||
|
||||
void qk_ucis_start(void) {
|
||||
qk_ucis_state.count = 0;
|
||||
qk_ucis_state.in_progress = true;
|
||||
|
||||
qk_ucis_start_user();
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void qk_ucis_start_user(void) {
|
||||
unicode_input_start();
|
||||
register_hex(0x2328);
|
||||
unicode_input_finish();
|
||||
}
|
||||
|
||||
static bool is_uni_seq(char *seq) {
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; seq[i]; i++) {
|
||||
uint16_t code;
|
||||
if (('1' <= seq[i]) && (seq[i] <= '0'))
|
||||
code = seq[i] - '1' + KC_1;
|
||||
else
|
||||
code = seq[i] - 'a' + KC_A;
|
||||
|
||||
if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
|
||||
return false;
|
||||
}
|
||||
|
||||
return (qk_ucis_state.codes[i] == KC_ENT ||
|
||||
qk_ucis_state.codes[i] == KC_SPC);
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void qk_ucis_symbol_fallback (void) {
|
||||
for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
|
||||
uint8_t code = qk_ucis_state.codes[i];
|
||||
register_code(code);
|
||||
unregister_code(code);
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void register_ucis(const char *hex) {
|
||||
for(int i = 0; hex[i]; i++) {
|
||||
uint8_t kc = 0;
|
||||
char c = hex[i];
|
||||
|
||||
switch (c) {
|
||||
case '0':
|
||||
kc = KC_0;
|
||||
break;
|
||||
case '1' ... '9':
|
||||
kc = c - '1' + KC_1;
|
||||
break;
|
||||
case 'a' ... 'f':
|
||||
kc = c - 'a' + KC_A;
|
||||
break;
|
||||
case 'A' ... 'F':
|
||||
kc = c - 'A' + KC_A;
|
||||
break;
|
||||
}
|
||||
|
||||
if (kc) {
|
||||
register_code (kc);
|
||||
unregister_code (kc);
|
||||
wait_ms (UNICODE_TYPE_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool process_ucis (uint16_t keycode, keyrecord_t *record) {
|
||||
uint8_t i;
|
||||
|
||||
if (!qk_ucis_state.in_progress)
|
||||
return true;
|
||||
|
||||
if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
|
||||
!(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!record->event.pressed)
|
||||
return true;
|
||||
|
||||
qk_ucis_state.codes[qk_ucis_state.count] = keycode;
|
||||
qk_ucis_state.count++;
|
||||
|
||||
if (keycode == KC_BSPC) {
|
||||
if (qk_ucis_state.count >= 2) {
|
||||
qk_ucis_state.count -= 2;
|
||||
return true;
|
||||
} else {
|
||||
qk_ucis_state.count--;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
|
||||
bool symbol_found = false;
|
||||
|
||||
for (i = qk_ucis_state.count; i > 0; i--) {
|
||||
register_code (KC_BSPC);
|
||||
unregister_code (KC_BSPC);
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
}
|
||||
|
||||
if (keycode == KC_ESC) {
|
||||
qk_ucis_state.in_progress = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
unicode_input_start();
|
||||
for (i = 0; ucis_symbol_table[i].symbol; i++) {
|
||||
if (is_uni_seq (ucis_symbol_table[i].symbol)) {
|
||||
symbol_found = true;
|
||||
register_ucis(ucis_symbol_table[i].code + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!symbol_found) {
|
||||
qk_ucis_symbol_fallback();
|
||||
}
|
||||
unicode_input_finish();
|
||||
|
||||
qk_ucis_state.in_progress = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
51
quantum/process_keycode/process_ucis.h
Normal file
51
quantum/process_keycode/process_ucis.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* Copyright 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_UCIS_H
|
||||
#define PROCESS_UCIS_H
|
||||
|
||||
#include "quantum.h"
|
||||
#include "process_unicode_common.h"
|
||||
|
||||
#ifndef UCIS_MAX_SYMBOL_LENGTH
|
||||
#define UCIS_MAX_SYMBOL_LENGTH 32
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *symbol;
|
||||
char *code;
|
||||
} qk_ucis_symbol_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t count;
|
||||
uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
|
||||
bool in_progress:1;
|
||||
} qk_ucis_state_t;
|
||||
|
||||
extern qk_ucis_state_t qk_ucis_state;
|
||||
|
||||
#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
|
||||
#define UCIS_SYM(name, code) {name, #code}
|
||||
|
||||
extern const qk_ucis_symbol_t ucis_symbol_table[];
|
||||
|
||||
void qk_ucis_start(void);
|
||||
void qk_ucis_start_user(void);
|
||||
void qk_ucis_symbol_fallback (void);
|
||||
void register_ucis(const char *hex);
|
||||
bool process_ucis (uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
#endif
|
|
@ -1,4 +1,20 @@
|
|||
/* Copyright 2016 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 "process_unicode.h"
|
||||
#include "action_util.h"
|
||||
|
||||
static uint8_t input_mode;
|
||||
static uint8_t first_flag = 0;
|
||||
|
@ -75,6 +91,7 @@ void register_hex(uint16_t hex) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool process_unicode(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode > QK_UNICODE && record->event.pressed) {
|
||||
if (first_flag == 0) {
|
||||
|
@ -89,182 +106,3 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record) {
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
__attribute__((weak))
|
||||
const uint32_t PROGMEM unicode_map[] = {
|
||||
};
|
||||
|
||||
void register_hex32(uint32_t hex) {
|
||||
uint8_t onzerostart = 1;
|
||||
for(int i = 7; i >= 0; i--) {
|
||||
if (i <= 3) {
|
||||
onzerostart = 0;
|
||||
}
|
||||
uint8_t digit = ((hex >> (i*4)) & 0xF);
|
||||
if (digit == 0) {
|
||||
if (onzerostart == 0) {
|
||||
register_code(hex_to_keycode(digit));
|
||||
unregister_code(hex_to_keycode(digit));
|
||||
}
|
||||
} else {
|
||||
register_code(hex_to_keycode(digit));
|
||||
unregister_code(hex_to_keycode(digit));
|
||||
onzerostart = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void unicode_map_input_error() {}
|
||||
|
||||
bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
|
||||
if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
|
||||
const uint32_t* map = unicode_map;
|
||||
uint16_t index = keycode & 0x7FF;
|
||||
uint32_t code = pgm_read_dword_far(&map[index]);
|
||||
if ((code > 0xFFFF && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
|
||||
// when character is out of range supported by the OS
|
||||
unicode_map_input_error();
|
||||
} else {
|
||||
unicode_input_start();
|
||||
register_hex32(code);
|
||||
unicode_input_finish();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UCIS_ENABLE
|
||||
qk_ucis_state_t qk_ucis_state;
|
||||
|
||||
void qk_ucis_start(void) {
|
||||
qk_ucis_state.count = 0;
|
||||
qk_ucis_state.in_progress = true;
|
||||
|
||||
qk_ucis_start_user();
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void qk_ucis_start_user(void) {
|
||||
unicode_input_start();
|
||||
register_hex(0x2328);
|
||||
unicode_input_finish();
|
||||
}
|
||||
|
||||
static bool is_uni_seq(char *seq) {
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; seq[i]; i++) {
|
||||
uint16_t code;
|
||||
if (('1' <= seq[i]) && (seq[i] <= '0'))
|
||||
code = seq[i] - '1' + KC_1;
|
||||
else
|
||||
code = seq[i] - 'a' + KC_A;
|
||||
|
||||
if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
|
||||
return false;
|
||||
}
|
||||
|
||||
return (qk_ucis_state.codes[i] == KC_ENT ||
|
||||
qk_ucis_state.codes[i] == KC_SPC);
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void qk_ucis_symbol_fallback (void) {
|
||||
for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
|
||||
uint8_t code = qk_ucis_state.codes[i];
|
||||
register_code(code);
|
||||
unregister_code(code);
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void register_ucis(const char *hex) {
|
||||
for(int i = 0; hex[i]; i++) {
|
||||
uint8_t kc = 0;
|
||||
char c = hex[i];
|
||||
|
||||
switch (c) {
|
||||
case '0':
|
||||
kc = KC_0;
|
||||
break;
|
||||
case '1' ... '9':
|
||||
kc = c - '1' + KC_1;
|
||||
break;
|
||||
case 'a' ... 'f':
|
||||
kc = c - 'a' + KC_A;
|
||||
break;
|
||||
case 'A' ... 'F':
|
||||
kc = c - 'A' + KC_A;
|
||||
break;
|
||||
}
|
||||
|
||||
if (kc) {
|
||||
register_code (kc);
|
||||
unregister_code (kc);
|
||||
wait_ms (UNICODE_TYPE_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool process_ucis (uint16_t keycode, keyrecord_t *record) {
|
||||
uint8_t i;
|
||||
|
||||
if (!qk_ucis_state.in_progress)
|
||||
return true;
|
||||
|
||||
if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
|
||||
!(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!record->event.pressed)
|
||||
return true;
|
||||
|
||||
qk_ucis_state.codes[qk_ucis_state.count] = keycode;
|
||||
qk_ucis_state.count++;
|
||||
|
||||
if (keycode == KC_BSPC) {
|
||||
if (qk_ucis_state.count >= 2) {
|
||||
qk_ucis_state.count -= 2;
|
||||
return true;
|
||||
} else {
|
||||
qk_ucis_state.count--;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
|
||||
bool symbol_found = false;
|
||||
|
||||
for (i = qk_ucis_state.count; i > 0; i--) {
|
||||
register_code (KC_BSPC);
|
||||
unregister_code (KC_BSPC);
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
}
|
||||
|
||||
if (keycode == KC_ESC) {
|
||||
qk_ucis_state.in_progress = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
unicode_input_start();
|
||||
for (i = 0; ucis_symbol_table[i].symbol; i++) {
|
||||
if (is_uni_seq (ucis_symbol_table[i].symbol)) {
|
||||
symbol_found = true;
|
||||
register_ucis(ucis_symbol_table[i].code + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!symbol_found) {
|
||||
qk_ucis_symbol_fallback();
|
||||
}
|
||||
unicode_input_finish();
|
||||
|
||||
qk_ucis_state.in_progress = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,166 +1,24 @@
|
|||
/* Copyright 2016 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/>.
|
||||
*/
|
||||
#ifndef PROCESS_UNICODE_H
|
||||
#define PROCESS_UNICODE_H
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
#define UC_OSX 0 // Mac OS X
|
||||
#define UC_LNX 1 // Linux
|
||||
#define UC_WIN 2 // Windows 'HexNumpad'
|
||||
#define UC_BSD 3 // BSD (not implemented)
|
||||
#define UC_WINC 4 // WinCompose https://github.com/samhocevar/wincompose
|
||||
|
||||
#ifndef UNICODE_TYPE_DELAY
|
||||
#define UNICODE_TYPE_DELAY 10
|
||||
#endif
|
||||
|
||||
void set_unicode_input_mode(uint8_t os_target);
|
||||
uint8_t get_unicode_input_mode(void);
|
||||
void unicode_input_start(void);
|
||||
void unicode_input_finish(void);
|
||||
void register_hex(uint16_t hex);
|
||||
#include "process_unicode_common.h"
|
||||
|
||||
bool process_unicode(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
bool process_unicode_map(uint16_t keycode, keyrecord_t *record);
|
||||
#endif
|
||||
|
||||
#ifdef UCIS_ENABLE
|
||||
#ifndef UCIS_MAX_SYMBOL_LENGTH
|
||||
#define UCIS_MAX_SYMBOL_LENGTH 32
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *symbol;
|
||||
char *code;
|
||||
} qk_ucis_symbol_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t count;
|
||||
uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
|
||||
bool in_progress:1;
|
||||
} qk_ucis_state_t;
|
||||
|
||||
extern qk_ucis_state_t qk_ucis_state;
|
||||
|
||||
#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
|
||||
#define UCIS_SYM(name, code) {name, #code}
|
||||
|
||||
extern const qk_ucis_symbol_t ucis_symbol_table[];
|
||||
|
||||
void qk_ucis_start(void);
|
||||
void qk_ucis_start_user(void);
|
||||
void qk_ucis_symbol_fallback (void);
|
||||
void register_ucis(const char *hex);
|
||||
bool process_ucis (uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
#endif
|
||||
|
||||
#define UC_BSPC UC(0x0008)
|
||||
|
||||
#define UC_SPC UC(0x0020)
|
||||
|
||||
#define UC_EXLM UC(0x0021)
|
||||
#define UC_DQUT UC(0x0022)
|
||||
#define UC_HASH UC(0x0023)
|
||||
#define UC_DLR UC(0x0024)
|
||||
#define UC_PERC UC(0x0025)
|
||||
#define UC_AMPR UC(0x0026)
|
||||
#define UC_QUOT UC(0x0027)
|
||||
#define UC_LPRN UC(0x0028)
|
||||
#define UC_RPRN UC(0x0029)
|
||||
#define UC_ASTR UC(0x002A)
|
||||
#define UC_PLUS UC(0x002B)
|
||||
#define UC_COMM UC(0x002C)
|
||||
#define UC_DASH UC(0x002D)
|
||||
#define UC_DOT UC(0x002E)
|
||||
#define UC_SLSH UC(0x002F)
|
||||
|
||||
#define UC_0 UC(0x0030)
|
||||
#define UC_1 UC(0x0031)
|
||||
#define UC_2 UC(0x0032)
|
||||
#define UC_3 UC(0x0033)
|
||||
#define UC_4 UC(0x0034)
|
||||
#define UC_5 UC(0x0035)
|
||||
#define UC_6 UC(0x0036)
|
||||
#define UC_7 UC(0x0037)
|
||||
#define UC_8 UC(0x0038)
|
||||
#define UC_9 UC(0x0039)
|
||||
|
||||
#define UC_COLN UC(0x003A)
|
||||
#define UC_SCLN UC(0x003B)
|
||||
#define UC_LT UC(0x003C)
|
||||
#define UC_EQL UC(0x003D)
|
||||
#define UC_GT UC(0x003E)
|
||||
#define UC_QUES UC(0x003F)
|
||||
#define UC_AT UC(0x0040)
|
||||
|
||||
#define UC_A UC(0x0041)
|
||||
#define UC_B UC(0x0042)
|
||||
#define UC_C UC(0x0043)
|
||||
#define UC_D UC(0x0044)
|
||||
#define UC_E UC(0x0045)
|
||||
#define UC_F UC(0x0046)
|
||||
#define UC_G UC(0x0047)
|
||||
#define UC_H UC(0x0048)
|
||||
#define UC_I UC(0x0049)
|
||||
#define UC_J UC(0x004A)
|
||||
#define UC_K UC(0x004B)
|
||||
#define UC_L UC(0x004C)
|
||||
#define UC_M UC(0x004D)
|
||||
#define UC_N UC(0x004E)
|
||||
#define UC_O UC(0x004F)
|
||||
#define UC_P UC(0x0050)
|
||||
#define UC_Q UC(0x0051)
|
||||
#define UC_R UC(0x0052)
|
||||
#define UC_S UC(0x0053)
|
||||
#define UC_T UC(0x0054)
|
||||
#define UC_U UC(0x0055)
|
||||
#define UC_V UC(0x0056)
|
||||
#define UC_W UC(0x0057)
|
||||
#define UC_X UC(0x0058)
|
||||
#define UC_Y UC(0x0059)
|
||||
#define UC_Z UC(0x005A)
|
||||
|
||||
#define UC_LBRC UC(0x005B)
|
||||
#define UC_BSLS UC(0x005C)
|
||||
#define UC_RBRC UC(0x005D)
|
||||
#define UC_CIRM UC(0x005E)
|
||||
#define UC_UNDR UC(0x005F)
|
||||
|
||||
#define UC_GRV UC(0x0060)
|
||||
|
||||
#define UC_a UC(0x0061)
|
||||
#define UC_b UC(0x0062)
|
||||
#define UC_c UC(0x0063)
|
||||
#define UC_d UC(0x0064)
|
||||
#define UC_e UC(0x0065)
|
||||
#define UC_f UC(0x0066)
|
||||
#define UC_g UC(0x0067)
|
||||
#define UC_h UC(0x0068)
|
||||
#define UC_i UC(0x0069)
|
||||
#define UC_j UC(0x006A)
|
||||
#define UC_k UC(0x006B)
|
||||
#define UC_l UC(0x006C)
|
||||
#define UC_m UC(0x006D)
|
||||
#define UC_n UC(0x006E)
|
||||
#define UC_o UC(0x006F)
|
||||
#define UC_p UC(0x0070)
|
||||
#define UC_q UC(0x0071)
|
||||
#define UC_r UC(0x0072)
|
||||
#define UC_s UC(0x0073)
|
||||
#define UC_t UC(0x0074)
|
||||
#define UC_u UC(0x0075)
|
||||
#define UC_v UC(0x0076)
|
||||
#define UC_w UC(0x0077)
|
||||
#define UC_x UC(0x0078)
|
||||
#define UC_y UC(0x0079)
|
||||
#define UC_z UC(0x007A)
|
||||
|
||||
#define UC_LCBR UC(0x007B)
|
||||
#define UC_PIPE UC(0x007C)
|
||||
#define UC_RCBR UC(0x007D)
|
||||
#define UC_TILD UC(0x007E)
|
||||
#define UC_DEL UC(0x007F)
|
||||
|
||||
#endif
|
||||
|
|
101
quantum/process_keycode/process_unicode_common.c
Normal file
101
quantum/process_keycode/process_unicode_common.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* Copyright 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 "process_unicode_common.h"
|
||||
|
||||
uint8_t mods;
|
||||
|
||||
void set_unicode_input_mode(uint8_t os_target)
|
||||
{
|
||||
input_mode = os_target;
|
||||
}
|
||||
|
||||
uint8_t get_unicode_input_mode(void) {
|
||||
return input_mode;
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void unicode_input_start (void) {
|
||||
// save current mods
|
||||
mods = keyboard_report->mods;
|
||||
|
||||
// unregister all mods to start from clean state
|
||||
if (mods & MOD_BIT(KC_LSFT)) unregister_code(KC_LSFT);
|
||||
if (mods & MOD_BIT(KC_RSFT)) unregister_code(KC_RSFT);
|
||||
if (mods & MOD_BIT(KC_LCTL)) unregister_code(KC_LCTL);
|
||||
if (mods & MOD_BIT(KC_RCTL)) unregister_code(KC_RCTL);
|
||||
if (mods & MOD_BIT(KC_LALT)) unregister_code(KC_LALT);
|
||||
if (mods & MOD_BIT(KC_RALT)) unregister_code(KC_RALT);
|
||||
if (mods & MOD_BIT(KC_LGUI)) unregister_code(KC_LGUI);
|
||||
if (mods & MOD_BIT(KC_RGUI)) unregister_code(KC_RGUI);
|
||||
|
||||
switch(input_mode) {
|
||||
case UC_OSX:
|
||||
register_code(KC_LALT);
|
||||
break;
|
||||
case UC_LNX:
|
||||
register_code(KC_LCTL);
|
||||
register_code(KC_LSFT);
|
||||
register_code(KC_U);
|
||||
unregister_code(KC_U);
|
||||
unregister_code(KC_LSFT);
|
||||
unregister_code(KC_LCTL);
|
||||
break;
|
||||
case UC_WIN:
|
||||
register_code(KC_LALT);
|
||||
register_code(KC_PPLS);
|
||||
unregister_code(KC_PPLS);
|
||||
break;
|
||||
case UC_WINC:
|
||||
register_code(KC_RALT);
|
||||
unregister_code(KC_RALT);
|
||||
register_code(KC_U);
|
||||
unregister_code(KC_U);
|
||||
}
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void unicode_input_finish (void) {
|
||||
switch(input_mode) {
|
||||
case UC_OSX:
|
||||
case UC_WIN:
|
||||
unregister_code(KC_LALT);
|
||||
break;
|
||||
case UC_LNX:
|
||||
register_code(KC_SPC);
|
||||
unregister_code(KC_SPC);
|
||||
break;
|
||||
}
|
||||
|
||||
// reregister previously set mods
|
||||
if (mods & MOD_BIT(KC_LSFT)) register_code(KC_LSFT);
|
||||
if (mods & MOD_BIT(KC_RSFT)) register_code(KC_RSFT);
|
||||
if (mods & MOD_BIT(KC_LCTL)) register_code(KC_LCTL);
|
||||
if (mods & MOD_BIT(KC_RCTL)) register_code(KC_RCTL);
|
||||
if (mods & MOD_BIT(KC_LALT)) register_code(KC_LALT);
|
||||
if (mods & MOD_BIT(KC_RALT)) register_code(KC_RALT);
|
||||
if (mods & MOD_BIT(KC_LGUI)) register_code(KC_LGUI);
|
||||
if (mods & MOD_BIT(KC_RGUI)) register_code(KC_RGUI);
|
||||
}
|
||||
|
||||
void register_hex(uint16_t hex) {
|
||||
for(int i = 3; i >= 0; i--) {
|
||||
uint8_t digit = ((hex >> (i*4)) & 0xF);
|
||||
register_code(hex_to_keycode(digit));
|
||||
unregister_code(hex_to_keycode(digit));
|
||||
}
|
||||
}
|
148
quantum/process_keycode/process_unicode_common.h
Normal file
148
quantum/process_keycode/process_unicode_common.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/* Copyright 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_UNICODE_COMMON_H
|
||||
#define PROCESS_UNICODE_COMMON_H
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
#ifndef UNICODE_TYPE_DELAY
|
||||
#define UNICODE_TYPE_DELAY 10
|
||||
#endif
|
||||
|
||||
__attribute__ ((unused))
|
||||
static uint8_t input_mode;
|
||||
|
||||
void set_unicode_input_mode(uint8_t os_target);
|
||||
uint8_t get_unicode_input_mode(void);
|
||||
void unicode_input_start(void);
|
||||
void unicode_input_finish(void);
|
||||
void register_hex(uint16_t hex);
|
||||
|
||||
#define UC_OSX 0 // Mac OS X
|
||||
#define UC_LNX 1 // Linux
|
||||
#define UC_WIN 2 // Windows 'HexNumpad'
|
||||
#define UC_BSD 3 // BSD (not implemented)
|
||||
#define UC_WINC 4 // WinCompose https://github.com/samhocevar/wincompose
|
||||
|
||||
#define UC_BSPC UC(0x0008)
|
||||
|
||||
#define UC_SPC UC(0x0020)
|
||||
|
||||
#define UC_EXLM UC(0x0021)
|
||||
#define UC_DQUT UC(0x0022)
|
||||
#define UC_HASH UC(0x0023)
|
||||
#define UC_DLR UC(0x0024)
|
||||
#define UC_PERC UC(0x0025)
|
||||
#define UC_AMPR UC(0x0026)
|
||||
#define UC_QUOT UC(0x0027)
|
||||
#define UC_LPRN UC(0x0028)
|
||||
#define UC_RPRN UC(0x0029)
|
||||
#define UC_ASTR UC(0x002A)
|
||||
#define UC_PLUS UC(0x002B)
|
||||
#define UC_COMM UC(0x002C)
|
||||
#define UC_DASH UC(0x002D)
|
||||
#define UC_DOT UC(0x002E)
|
||||
#define UC_SLSH UC(0x002F)
|
||||
|
||||
#define UC_0 UC(0x0030)
|
||||
#define UC_1 UC(0x0031)
|
||||
#define UC_2 UC(0x0032)
|
||||
#define UC_3 UC(0x0033)
|
||||
#define UC_4 UC(0x0034)
|
||||
#define UC_5 UC(0x0035)
|
||||
#define UC_6 UC(0x0036)
|
||||
#define UC_7 UC(0x0037)
|
||||
#define UC_8 UC(0x0038)
|
||||
#define UC_9 UC(0x0039)
|
||||
|
||||
#define UC_COLN UC(0x003A)
|
||||
#define UC_SCLN UC(0x003B)
|
||||
#define UC_LT UC(0x003C)
|
||||
#define UC_EQL UC(0x003D)
|
||||
#define UC_GT UC(0x003E)
|
||||
#define UC_QUES UC(0x003F)
|
||||
#define UC_AT UC(0x0040)
|
||||
|
||||
#define UC_A UC(0x0041)
|
||||
#define UC_B UC(0x0042)
|
||||
#define UC_C UC(0x0043)
|
||||
#define UC_D UC(0x0044)
|
||||
#define UC_E UC(0x0045)
|
||||
#define UC_F UC(0x0046)
|
||||
#define UC_G UC(0x0047)
|
||||
#define UC_H UC(0x0048)
|
||||
#define UC_I UC(0x0049)
|
||||
#define UC_J UC(0x004A)
|
||||
#define UC_K UC(0x004B)
|
||||
#define UC_L UC(0x004C)
|
||||
#define UC_M UC(0x004D)
|
||||
#define UC_N UC(0x004E)
|
||||
#define UC_O UC(0x004F)
|
||||
#define UC_P UC(0x0050)
|
||||
#define UC_Q UC(0x0051)
|
||||
#define UC_R UC(0x0052)
|
||||
#define UC_S UC(0x0053)
|
||||
#define UC_T UC(0x0054)
|
||||
#define UC_U UC(0x0055)
|
||||
#define UC_V UC(0x0056)
|
||||
#define UC_W UC(0x0057)
|
||||
#define UC_X UC(0x0058)
|
||||
#define UC_Y UC(0x0059)
|
||||
#define UC_Z UC(0x005A)
|
||||
|
||||
#define UC_LBRC UC(0x005B)
|
||||
#define UC_BSLS UC(0x005C)
|
||||
#define UC_RBRC UC(0x005D)
|
||||
#define UC_CIRM UC(0x005E)
|
||||
#define UC_UNDR UC(0x005F)
|
||||
|
||||
#define UC_GRV UC(0x0060)
|
||||
|
||||
#define UC_a UC(0x0061)
|
||||
#define UC_b UC(0x0062)
|
||||
#define UC_c UC(0x0063)
|
||||
#define UC_d UC(0x0064)
|
||||
#define UC_e UC(0x0065)
|
||||
#define UC_f UC(0x0066)
|
||||
#define UC_g UC(0x0067)
|
||||
#define UC_h UC(0x0068)
|
||||
#define UC_i UC(0x0069)
|
||||
#define UC_j UC(0x006A)
|
||||
#define UC_k UC(0x006B)
|
||||
#define UC_l UC(0x006C)
|
||||
#define UC_m UC(0x006D)
|
||||
#define UC_n UC(0x006E)
|
||||
#define UC_o UC(0x006F)
|
||||
#define UC_p UC(0x0070)
|
||||
#define UC_q UC(0x0071)
|
||||
#define UC_r UC(0x0072)
|
||||
#define UC_s UC(0x0073)
|
||||
#define UC_t UC(0x0074)
|
||||
#define UC_u UC(0x0075)
|
||||
#define UC_v UC(0x0076)
|
||||
#define UC_w UC(0x0077)
|
||||
#define UC_x UC(0x0078)
|
||||
#define UC_y UC(0x0079)
|
||||
#define UC_z UC(0x007A)
|
||||
|
||||
#define UC_LCBR UC(0x007B)
|
||||
#define UC_PIPE UC(0x007C)
|
||||
#define UC_RCBR UC(0x007D)
|
||||
#define UC_TILD UC(0x007E)
|
||||
#define UC_DEL UC(0x007F)
|
||||
|
||||
#endif
|
72
quantum/process_keycode/process_unicodemap.c
Normal file
72
quantum/process_keycode/process_unicodemap.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Copyright 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 "process_unicodemap.h"
|
||||
#include "process_unicode_common.h"
|
||||
|
||||
__attribute__((weak))
|
||||
const uint32_t PROGMEM unicode_map[] = {
|
||||
};
|
||||
|
||||
void register_hex32(uint32_t hex) {
|
||||
bool onzerostart = true;
|
||||
for(int i = 7; i >= 0; i--) {
|
||||
if (i <= 3) {
|
||||
onzerostart = false;
|
||||
}
|
||||
uint8_t digit = ((hex >> (i*4)) & 0xF);
|
||||
if (digit == 0) {
|
||||
if (!onzerostart) {
|
||||
register_code(hex_to_keycode(digit));
|
||||
unregister_code(hex_to_keycode(digit));
|
||||
}
|
||||
} else {
|
||||
register_code(hex_to_keycode(digit));
|
||||
unregister_code(hex_to_keycode(digit));
|
||||
onzerostart = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void unicode_map_input_error() {}
|
||||
|
||||
bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
|
||||
uint8_t input_mode = get_unicode_input_mode();
|
||||
if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
|
||||
const uint32_t* map = unicode_map;
|
||||
uint16_t index = keycode - QK_UNICODE_MAP;
|
||||
uint32_t code = pgm_read_dword_far(&map[index]);
|
||||
if (code > 0xFFFF && code <= 0x10ffff && input_mode == UC_OSX) {
|
||||
// Convert to UTF-16 surrogate pair
|
||||
code -= 0x10000;
|
||||
uint32_t lo = code & 0x3ff;
|
||||
uint32_t hi = (code & 0xffc00) >> 10;
|
||||
unicode_input_start();
|
||||
register_hex32(hi + 0xd800);
|
||||
register_hex32(lo + 0xdc00);
|
||||
unicode_input_finish();
|
||||
} else if ((code > 0x10ffff && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
|
||||
// when character is out of range supported by the OS
|
||||
unicode_map_input_error();
|
||||
} else {
|
||||
unicode_input_start();
|
||||
register_hex32(code);
|
||||
unicode_input_finish();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
25
quantum/process_keycode/process_unicodemap.h
Normal file
25
quantum/process_keycode/process_unicodemap.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* Copyright 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/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_UNICODEMAP_H
|
||||
#define PROCESS_UNICODEMAP_H
|
||||
|
||||
#include "quantum.h"
|
||||
#include "process_unicode_common.h"
|
||||
|
||||
void unicode_map_input_error(void);
|
||||
bool process_unicode_map(uint16_t keycode, keyrecord_t *record);
|
||||
#endif
|
|
@ -1,4 +1,34 @@
|
|||
/* 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"
|
||||
#ifdef PROTOCOL_LUFA
|
||||
#include "outputselect.h"
|
||||
#endif
|
||||
|
||||
#ifndef TAPPING_TERM
|
||||
#define TAPPING_TERM 200
|
||||
#endif
|
||||
|
||||
#include "backlight.h"
|
||||
extern backlight_config_t backlight_config;
|
||||
|
||||
#ifdef FAUXCLICKY_ENABLE
|
||||
#include "fauxclicky.h"
|
||||
#endif
|
||||
|
||||
static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
|
||||
switch (code) {
|
||||
|
@ -17,6 +47,8 @@ static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
|
|||
if (code & QK_LGUI)
|
||||
f(KC_LGUI);
|
||||
|
||||
if (code < QK_RMODS_MIN) return;
|
||||
|
||||
if (code & QK_RCTL)
|
||||
f(KC_RCTL);
|
||||
if (code & QK_RSFT)
|
||||
|
@ -27,14 +59,42 @@ static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
|
|||
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) {
|
||||
do_code16 (code, register_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);
|
||||
do_code16 (code, unregister_code);
|
||||
if (IS_MOD(code) || code == KC_NO) {
|
||||
do_code16 (code, qk_unregister_mods);
|
||||
} else {
|
||||
do_code16 (code, qk_unregister_weak_mods);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
|
@ -54,8 +114,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|||
|
||||
void reset_keyboard(void) {
|
||||
clear_keyboard();
|
||||
#ifdef AUDIO_ENABLE
|
||||
stop_all_notes();
|
||||
#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_ENABLE_BASIC))
|
||||
music_all_notes_off();
|
||||
shutdown_user();
|
||||
#endif
|
||||
wait_ms(250);
|
||||
|
@ -75,6 +135,7 @@ void reset_keyboard(void) {
|
|||
#endif
|
||||
|
||||
static bool shift_interrupted[2] = {0, 0};
|
||||
static uint16_t scs_timer = 0;
|
||||
|
||||
bool process_record_quantum(keyrecord_t *record) {
|
||||
|
||||
|
@ -108,10 +169,13 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
|
||||
if (!(
|
||||
process_record_kb(keycode, record) &&
|
||||
#ifdef MIDI_ENABLE
|
||||
#if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)
|
||||
process_midi(keycode, record) &&
|
||||
#endif
|
||||
#ifdef AUDIO_ENABLE
|
||||
process_audio(keycode, record) &&
|
||||
#endif
|
||||
#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
||||
process_music(keycode, record) &&
|
||||
#endif
|
||||
#ifdef TAP_DANCE_ENABLE
|
||||
|
@ -123,12 +187,18 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
#ifndef DISABLE_CHORDING
|
||||
process_chording(keycode, record) &&
|
||||
#endif
|
||||
#ifdef COMBO_ENABLE
|
||||
process_combo(keycode, record) &&
|
||||
#endif
|
||||
#ifdef UNICODE_ENABLE
|
||||
process_unicode(keycode, record) &&
|
||||
#endif
|
||||
#ifdef UCIS_ENABLE
|
||||
process_ucis(keycode, record) &&
|
||||
#endif
|
||||
#ifdef PRINTING_ENABLE
|
||||
process_printer(keycode, record) &&
|
||||
#endif
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
process_unicode_map(keycode, record) &&
|
||||
#endif
|
||||
|
@ -152,6 +222,26 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
}
|
||||
return false;
|
||||
break;
|
||||
#ifdef FAUXCLICKY_ENABLE
|
||||
case FC_TOG:
|
||||
if (record->event.pressed) {
|
||||
FAUXCLICKY_TOGGLE;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case FC_ON:
|
||||
if (record->event.pressed) {
|
||||
FAUXCLICKY_ON;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case FC_OFF:
|
||||
if (record->event.pressed) {
|
||||
FAUXCLICKY_OFF;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
#endif
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
case RGB_TOG:
|
||||
if (record->event.pressed) {
|
||||
|
@ -202,6 +292,28 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
return false;
|
||||
break;
|
||||
#endif
|
||||
#ifdef PROTOCOL_LUFA
|
||||
case OUT_AUTO:
|
||||
if (record->event.pressed) {
|
||||
set_output(OUTPUT_AUTO);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case OUT_USB:
|
||||
if (record->event.pressed) {
|
||||
set_output(OUTPUT_USB);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
#ifdef BLUETOOTH_ENABLE
|
||||
case OUT_BT:
|
||||
if (record->event.pressed) {
|
||||
set_output(OUTPUT_BLUETOOTH);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
|
||||
if (record->event.pressed) {
|
||||
// MAGIC actions (BOOTMAGIC without the boot)
|
||||
|
@ -283,6 +395,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
case KC_LSPO: {
|
||||
if (record->event.pressed) {
|
||||
shift_interrupted[0] = false;
|
||||
scs_timer = timer_read ();
|
||||
register_mods(MOD_BIT(KC_LSFT));
|
||||
}
|
||||
else {
|
||||
|
@ -292,7 +405,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
shift_interrupted[1] = true;
|
||||
}
|
||||
#endif
|
||||
if (!shift_interrupted[0]) {
|
||||
if (!shift_interrupted[0] && timer_elapsed(scs_timer) < TAPPING_TERM) {
|
||||
register_code(LSPO_KEY);
|
||||
unregister_code(LSPO_KEY);
|
||||
}
|
||||
|
@ -305,6 +418,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
case KC_RSPC: {
|
||||
if (record->event.pressed) {
|
||||
shift_interrupted[1] = false;
|
||||
scs_timer = timer_read ();
|
||||
register_mods(MOD_BIT(KC_RSFT));
|
||||
}
|
||||
else {
|
||||
|
@ -314,7 +428,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
shift_interrupted[1] = true;
|
||||
}
|
||||
#endif
|
||||
if (!shift_interrupted[1]) {
|
||||
if (!shift_interrupted[1] && timer_elapsed(scs_timer) < TAPPING_TERM) {
|
||||
register_code(RSPC_KEY);
|
||||
unregister_code(RSPC_KEY);
|
||||
}
|
||||
|
@ -496,6 +610,15 @@ void matrix_scan_quantum() {
|
|||
#ifdef TAP_DANCE_ENABLE
|
||||
matrix_scan_tap_dance();
|
||||
#endif
|
||||
|
||||
#ifdef COMBO_ENABLE
|
||||
matrix_scan_combo();
|
||||
#endif
|
||||
|
||||
#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
|
||||
backlight_task();
|
||||
#endif
|
||||
|
||||
matrix_scan_kb();
|
||||
}
|
||||
|
||||
|
@ -513,34 +636,45 @@ static const uint8_t backlight_pin = BACKLIGHT_PIN;
|
|||
# define COM1x1 COM1A1
|
||||
# define OCR1x OCR1A
|
||||
#else
|
||||
# error "Backlight pin not supported - use B5, B6, or B7"
|
||||
# define NO_BACKLIGHT_CLOCK
|
||||
#endif
|
||||
|
||||
#ifndef BACKLIGHT_ON_STATE
|
||||
#define BACKLIGHT_ON_STATE 0
|
||||
#endif
|
||||
|
||||
__attribute__ ((weak))
|
||||
void backlight_init_ports(void)
|
||||
{
|
||||
|
||||
// Setup backlight pin as output and output low.
|
||||
// Setup backlight pin as output and output to on state.
|
||||
// DDRx |= n
|
||||
_SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
|
||||
// PORTx &= ~n
|
||||
_SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
|
||||
#if BACKLIGHT_ON_STATE == 0
|
||||
// PORTx &= ~n
|
||||
_SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
|
||||
#else
|
||||
// PORTx |= n
|
||||
_SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
|
||||
#endif
|
||||
|
||||
// Use full 16-bit resolution.
|
||||
ICR1 = 0xFFFF;
|
||||
#ifndef NO_BACKLIGHT_CLOCK
|
||||
// Use full 16-bit resolution.
|
||||
ICR1 = 0xFFFF;
|
||||
|
||||
// I could write a wall of text here to explain... but TL;DW
|
||||
// Go read the ATmega32u4 datasheet.
|
||||
// And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
|
||||
// I could write a wall of text here to explain... but TL;DW
|
||||
// Go read the ATmega32u4 datasheet.
|
||||
// And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
|
||||
|
||||
// Pin PB7 = OCR1C (Timer 1, Channel C)
|
||||
// Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
|
||||
// (i.e. start high, go low when counter matches.)
|
||||
// WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
|
||||
// Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
|
||||
// Pin PB7 = OCR1C (Timer 1, Channel C)
|
||||
// Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
|
||||
// (i.e. start high, go low when counter matches.)
|
||||
// WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
|
||||
// Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
|
||||
|
||||
TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
|
||||
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||
TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
|
||||
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||
#endif
|
||||
|
||||
backlight_init();
|
||||
#ifdef BACKLIGHT_BREATHING
|
||||
|
@ -552,30 +686,73 @@ __attribute__ ((weak))
|
|||
void backlight_set(uint8_t level)
|
||||
{
|
||||
// Prevent backlight blink on lowest level
|
||||
// PORTx &= ~n
|
||||
_SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
|
||||
// #if BACKLIGHT_ON_STATE == 0
|
||||
// // PORTx &= ~n
|
||||
// _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
|
||||
// #else
|
||||
// // PORTx |= n
|
||||
// _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
|
||||
// #endif
|
||||
|
||||
if ( level == 0 ) {
|
||||
// Turn off PWM control on backlight pin, revert to output low.
|
||||
TCCR1A &= ~(_BV(COM1x1));
|
||||
OCR1x = 0x0;
|
||||
} else if ( level == BACKLIGHT_LEVELS ) {
|
||||
// Turn on PWM control of backlight pin
|
||||
TCCR1A |= _BV(COM1x1);
|
||||
// Set the brightness
|
||||
OCR1x = 0xFFFF;
|
||||
} else {
|
||||
// Turn on PWM control of backlight pin
|
||||
TCCR1A |= _BV(COM1x1);
|
||||
// Set the brightness
|
||||
OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
|
||||
}
|
||||
#ifndef NO_BACKLIGHT_CLOCK
|
||||
// Turn off PWM control on backlight pin, revert to output low.
|
||||
TCCR1A &= ~(_BV(COM1x1));
|
||||
OCR1x = 0x0;
|
||||
#else
|
||||
// #if BACKLIGHT_ON_STATE == 0
|
||||
// // PORTx |= n
|
||||
// _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
|
||||
// #else
|
||||
// // PORTx &= ~n
|
||||
// _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
|
||||
// #endif
|
||||
#endif
|
||||
}
|
||||
#ifndef NO_BACKLIGHT_CLOCK
|
||||
else if ( level == BACKLIGHT_LEVELS ) {
|
||||
// Turn on PWM control of backlight pin
|
||||
TCCR1A |= _BV(COM1x1);
|
||||
// Set the brightness
|
||||
OCR1x = 0xFFFF;
|
||||
}
|
||||
else {
|
||||
// Turn on PWM control of backlight pin
|
||||
TCCR1A |= _BV(COM1x1);
|
||||
// Set the brightness
|
||||
OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BACKLIGHT_BREATHING
|
||||
breathing_intensity_default();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t backlight_tick = 0;
|
||||
|
||||
void backlight_task(void) {
|
||||
#ifdef NO_BACKLIGHT_CLOCK
|
||||
if ((0xFFFF >> ((BACKLIGHT_LEVELS - backlight_config.level) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
|
||||
#if BACKLIGHT_ON_STATE == 0
|
||||
// PORTx &= ~n
|
||||
_SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
|
||||
#else
|
||||
// PORTx |= n
|
||||
_SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
|
||||
#endif
|
||||
} else {
|
||||
#if BACKLIGHT_ON_STATE == 0
|
||||
// PORTx |= n
|
||||
_SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
|
||||
#else
|
||||
// PORTx &= ~n
|
||||
_SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
|
||||
#endif
|
||||
}
|
||||
backlight_tick = (backlight_tick + 1) % 16;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BACKLIGHT_BREATHING
|
||||
|
||||
|
@ -799,6 +976,64 @@ void backlight_set(uint8_t level)
|
|||
#endif // backlight
|
||||
|
||||
|
||||
// Functions for spitting out values
|
||||
//
|
||||
|
||||
void send_dword(uint32_t number) { // this might not actually work
|
||||
uint16_t word = (number >> 16);
|
||||
send_word(word);
|
||||
send_word(number & 0xFFFFUL);
|
||||
}
|
||||
|
||||
void send_word(uint16_t number) {
|
||||
uint8_t byte = number >> 8;
|
||||
send_byte(byte);
|
||||
send_byte(number & 0xFF);
|
||||
}
|
||||
|
||||
void send_byte(uint8_t number) {
|
||||
uint8_t nibble = number >> 4;
|
||||
send_nibble(nibble);
|
||||
send_nibble(number & 0xF);
|
||||
}
|
||||
|
||||
void send_nibble(uint8_t number) {
|
||||
switch (number) {
|
||||
case 0:
|
||||
register_code(KC_0);
|
||||
unregister_code(KC_0);
|
||||
break;
|
||||
case 1 ... 9:
|
||||
register_code(KC_1 + (number - 1));
|
||||
unregister_code(KC_1 + (number - 1));
|
||||
break;
|
||||
case 0xA ... 0xF:
|
||||
register_code(KC_A + (number - 0xA));
|
||||
unregister_code(KC_A + (number - 0xA));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__attribute__((weak))
|
||||
uint16_t hex_to_keycode(uint8_t hex)
|
||||
{
|
||||
if (hex == 0x0) {
|
||||
return KC_0;
|
||||
} else if (hex < 0xA) {
|
||||
return KC_1 + (hex - 0x1);
|
||||
} else {
|
||||
return KC_A + (hex - 0xA);
|
||||
}
|
||||
}
|
||||
|
||||
void api_send_unicode(uint32_t unicode) {
|
||||
#ifdef API_ENABLE
|
||||
uint8_t chunk[4];
|
||||
dword_to_bytes(unicode, chunk);
|
||||
MT_SEND_DATA(DT_UNICODE, chunk, 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void led_set_user(uint8_t usb_led) {
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016-2017 Erez Zukerman, 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/>.
|
||||
*/
|
||||
#ifndef QUANTUM_H
|
||||
#define QUANTUM_H
|
||||
|
||||
|
@ -15,7 +30,6 @@
|
|||
#ifdef RGBLIGHT_ENABLE
|
||||
#include "rgblight.h"
|
||||
#endif
|
||||
|
||||
#include "action_layer.h"
|
||||
#include "eeconfig.h"
|
||||
#include <stddef.h>
|
||||
|
@ -36,11 +50,16 @@ extern uint32_t default_layer_state;
|
|||
|
||||
#ifdef MIDI_ENABLE
|
||||
#include <lufa.h>
|
||||
#ifdef MIDI_ADVANCED
|
||||
#include "process_midi.h"
|
||||
#endif
|
||||
#endif // MIDI_ENABLE
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
#include "audio.h"
|
||||
#include "process_audio.h"
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
||||
#include "process_music.h"
|
||||
#endif
|
||||
|
||||
|
@ -57,8 +76,24 @@ extern uint32_t default_layer_state;
|
|||
#include "process_unicode.h"
|
||||
#endif
|
||||
|
||||
#ifdef UCIS_ENABLE
|
||||
#include "process_ucis.h"
|
||||
#endif
|
||||
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
#include "process_unicodemap.h"
|
||||
#endif
|
||||
|
||||
#include "process_tap_dance.h"
|
||||
|
||||
#ifdef PRINTING_ENABLE
|
||||
#include "process_printer.h"
|
||||
#endif
|
||||
|
||||
#ifdef COMBO_ENABLE
|
||||
#include "process_combo.h"
|
||||
#endif
|
||||
|
||||
#define SEND_STRING(str) send_string(PSTR(str))
|
||||
void send_string(const char *str);
|
||||
|
||||
|
@ -88,6 +123,7 @@ void unregister_code16 (uint16_t code);
|
|||
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
void backlight_init_ports(void);
|
||||
void backlight_task(void);
|
||||
|
||||
#ifdef BACKLIGHT_BREATHING
|
||||
void breathing_enable(void);
|
||||
|
@ -106,8 +142,15 @@ void breathing_speed_dec(uint8_t value);
|
|||
#endif
|
||||
|
||||
#endif
|
||||
void send_dword(uint32_t number);
|
||||
void send_word(uint16_t number);
|
||||
void send_byte(uint8_t number);
|
||||
void send_nibble(uint8_t number);
|
||||
uint16_t hex_to_keycode(uint8_t hex);
|
||||
|
||||
void led_set_user(uint8_t usb_led);
|
||||
void led_set_kb(uint8_t usb_led);
|
||||
|
||||
void api_send_unicode(uint32_t unicode);
|
||||
|
||||
#endif
|
||||
|
|
600
quantum/quantum_keycodes.h
Normal file
600
quantum/quantum_keycodes.h
Normal file
|
@ -0,0 +1,600 @@
|
|||
/* 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/>.
|
||||
*/
|
||||
#ifndef QUANTUM_KEYCODES_H
|
||||
#define QUANTUM_KEYCODES_H
|
||||
|
||||
#ifndef MIDI_ENABLE_STRICT
|
||||
#define MIDI_ENABLE_STRICT 0
|
||||
#endif
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED))
|
||||
#ifndef MIDI_TONE_KEYCODE_OCTAVES
|
||||
#define MIDI_TONE_KEYCODE_OCTAVES 3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum quantum_keycodes {
|
||||
// Ranges used in shortucuts - not to be used directly
|
||||
QK_TMK = 0x0000,
|
||||
QK_TMK_MAX = 0x00FF,
|
||||
QK_MODS = 0x0100,
|
||||
QK_LCTL = 0x0100,
|
||||
QK_LSFT = 0x0200,
|
||||
QK_LALT = 0x0400,
|
||||
QK_LGUI = 0x0800,
|
||||
QK_RMODS_MIN = 0x1000,
|
||||
QK_RCTL = 0x1100,
|
||||
QK_RSFT = 0x1200,
|
||||
QK_RALT = 0x1400,
|
||||
QK_RGUI = 0x1800,
|
||||
QK_MODS_MAX = 0x1FFF,
|
||||
QK_FUNCTION = 0x2000,
|
||||
QK_FUNCTION_MAX = 0x2FFF,
|
||||
QK_MACRO = 0x3000,
|
||||
QK_MACRO_MAX = 0x3FFF,
|
||||
QK_LAYER_TAP = 0x4000,
|
||||
QK_LAYER_TAP_MAX = 0x4FFF,
|
||||
QK_TO = 0x5000,
|
||||
QK_TO_MAX = 0x50FF,
|
||||
QK_MOMENTARY = 0x5100,
|
||||
QK_MOMENTARY_MAX = 0x51FF,
|
||||
QK_DEF_LAYER = 0x5200,
|
||||
QK_DEF_LAYER_MAX = 0x52FF,
|
||||
QK_TOGGLE_LAYER = 0x5300,
|
||||
QK_TOGGLE_LAYER_MAX = 0x53FF,
|
||||
QK_ONE_SHOT_LAYER = 0x5400,
|
||||
QK_ONE_SHOT_LAYER_MAX = 0x54FF,
|
||||
QK_ONE_SHOT_MOD = 0x5500,
|
||||
QK_ONE_SHOT_MOD_MAX = 0x55FF,
|
||||
#ifndef DISABLE_CHORDING
|
||||
QK_CHORDING = 0x5600,
|
||||
QK_CHORDING_MAX = 0x56FF,
|
||||
#endif
|
||||
QK_TAP_DANCE = 0x5700,
|
||||
QK_TAP_DANCE_MAX = 0x57FF,
|
||||
QK_LAYER_TAP_TOGGLE = 0x5800,
|
||||
QK_LAYER_TAP_TOGGLE_MAX = 0x58FF,
|
||||
QK_MOD_TAP = 0x6000,
|
||||
QK_MOD_TAP_MAX = 0x7FFF,
|
||||
#if defined(UNICODEMAP_ENABLE) && defined(UNICODE_ENABLE)
|
||||
#error "Cannot enable both UNICODEMAP && UNICODE"
|
||||
#endif
|
||||
#ifdef UNICODE_ENABLE
|
||||
QK_UNICODE = 0x8000,
|
||||
QK_UNICODE_MAX = 0xFFFF,
|
||||
#endif
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
QK_UNICODE_MAP = 0x8000,
|
||||
QK_UNICODE_MAP_MAX = 0x83FF,
|
||||
#endif
|
||||
|
||||
// Loose keycodes - to be used directly
|
||||
|
||||
RESET = 0x5C00,
|
||||
DEBUG,
|
||||
MAGIC_SWAP_CONTROL_CAPSLOCK,
|
||||
MAGIC_CAPSLOCK_TO_CONTROL,
|
||||
MAGIC_SWAP_LALT_LGUI,
|
||||
MAGIC_SWAP_RALT_RGUI,
|
||||
MAGIC_NO_GUI,
|
||||
MAGIC_SWAP_GRAVE_ESC,
|
||||
MAGIC_SWAP_BACKSLASH_BACKSPACE,
|
||||
MAGIC_HOST_NKRO,
|
||||
MAGIC_SWAP_ALT_GUI,
|
||||
MAGIC_UNSWAP_CONTROL_CAPSLOCK,
|
||||
MAGIC_UNCAPSLOCK_TO_CONTROL,
|
||||
MAGIC_UNSWAP_LALT_LGUI,
|
||||
MAGIC_UNSWAP_RALT_RGUI,
|
||||
MAGIC_UNNO_GUI,
|
||||
MAGIC_UNSWAP_GRAVE_ESC,
|
||||
MAGIC_UNSWAP_BACKSLASH_BACKSPACE,
|
||||
MAGIC_UNHOST_NKRO,
|
||||
MAGIC_UNSWAP_ALT_GUI,
|
||||
MAGIC_TOGGLE_NKRO,
|
||||
|
||||
// Leader key
|
||||
#ifndef DISABLE_LEADER
|
||||
KC_LEAD,
|
||||
#endif
|
||||
|
||||
// Audio on/off/toggle
|
||||
AU_ON,
|
||||
AU_OFF,
|
||||
AU_TOG,
|
||||
|
||||
#ifdef FAUXCLICKY_ENABLE
|
||||
// Faux clicky
|
||||
FC_ON,
|
||||
FC_OFF,
|
||||
FC_TOG,
|
||||
#endif
|
||||
|
||||
// Music mode on/off/toggle
|
||||
MU_ON,
|
||||
MU_OFF,
|
||||
MU_TOG,
|
||||
|
||||
// Music voice iterate
|
||||
MUV_IN,
|
||||
MUV_DE,
|
||||
|
||||
// Midi
|
||||
#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
||||
MI_ON, // send midi notes when music mode is enabled
|
||||
MI_OFF, // don't send midi notes when music mode is enabled
|
||||
#endif
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED))
|
||||
MIDI_TONE_MIN,
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 0
|
||||
MI_C = MIDI_TONE_MIN,
|
||||
MI_Cs,
|
||||
MI_Db = MI_Cs,
|
||||
MI_D,
|
||||
MI_Ds,
|
||||
MI_Eb = MI_Ds,
|
||||
MI_E,
|
||||
MI_F,
|
||||
MI_Fs,
|
||||
MI_Gb = MI_Fs,
|
||||
MI_G,
|
||||
MI_Gs,
|
||||
MI_Ab = MI_Gs,
|
||||
MI_A,
|
||||
MI_As,
|
||||
MI_Bb = MI_As,
|
||||
MI_B,
|
||||
#endif
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 1
|
||||
MI_C_1,
|
||||
MI_Cs_1,
|
||||
MI_Db_1 = MI_Cs_1,
|
||||
MI_D_1,
|
||||
MI_Ds_1,
|
||||
MI_Eb_1 = MI_Ds_1,
|
||||
MI_E_1,
|
||||
MI_F_1,
|
||||
MI_Fs_1,
|
||||
MI_Gb_1 = MI_Fs_1,
|
||||
MI_G_1,
|
||||
MI_Gs_1,
|
||||
MI_Ab_1 = MI_Gs_1,
|
||||
MI_A_1,
|
||||
MI_As_1,
|
||||
MI_Bb_1 = MI_As_1,
|
||||
MI_B_1,
|
||||
#endif
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 2
|
||||
MI_C_2,
|
||||
MI_Cs_2,
|
||||
MI_Db_2 = MI_Cs_2,
|
||||
MI_D_2,
|
||||
MI_Ds_2,
|
||||
MI_Eb_2 = MI_Ds_2,
|
||||
MI_E_2,
|
||||
MI_F_2,
|
||||
MI_Fs_2,
|
||||
MI_Gb_2 = MI_Fs_2,
|
||||
MI_G_2,
|
||||
MI_Gs_2,
|
||||
MI_Ab_2 = MI_Gs_2,
|
||||
MI_A_2,
|
||||
MI_As_2,
|
||||
MI_Bb_2 = MI_As_2,
|
||||
MI_B_2,
|
||||
#endif
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 3
|
||||
MI_C_3,
|
||||
MI_Cs_3,
|
||||
MI_Db_3 = MI_Cs_3,
|
||||
MI_D_3,
|
||||
MI_Ds_3,
|
||||
MI_Eb_3 = MI_Ds_3,
|
||||
MI_E_3,
|
||||
MI_F_3,
|
||||
MI_Fs_3,
|
||||
MI_Gb_3 = MI_Fs_3,
|
||||
MI_G_3,
|
||||
MI_Gs_3,
|
||||
MI_Ab_3 = MI_Gs_3,
|
||||
MI_A_3,
|
||||
MI_As_3,
|
||||
MI_Bb_3 = MI_As_3,
|
||||
MI_B_3,
|
||||
#endif
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 4
|
||||
MI_C_4,
|
||||
MI_Cs_4,
|
||||
MI_Db_4 = MI_Cs_4,
|
||||
MI_D_4,
|
||||
MI_Ds_4,
|
||||
MI_Eb_4 = MI_Ds_4,
|
||||
MI_E_4,
|
||||
MI_F_4,
|
||||
MI_Fs_4,
|
||||
MI_Gb_4 = MI_Fs_4,
|
||||
MI_G_4,
|
||||
MI_Gs_4,
|
||||
MI_Ab_4 = MI_Gs_4,
|
||||
MI_A_4,
|
||||
MI_As_4,
|
||||
MI_Bb_4 = MI_As_4,
|
||||
MI_B_4,
|
||||
#endif
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5
|
||||
MI_C_5,
|
||||
MI_Cs_5,
|
||||
MI_Db_5 = MI_Cs_5,
|
||||
MI_D_5,
|
||||
MI_Ds_5,
|
||||
MI_Eb_5 = MI_Ds_5,
|
||||
MI_E_5,
|
||||
MI_F_5,
|
||||
MI_Fs_5,
|
||||
MI_Gb_5 = MI_Fs_5,
|
||||
MI_G_5,
|
||||
MI_Gs_5,
|
||||
MI_Ab_5 = MI_Gs_5,
|
||||
MI_A_5,
|
||||
MI_As_5,
|
||||
MI_Bb_5 = MI_As_5,
|
||||
MI_B_5,
|
||||
#endif
|
||||
|
||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5
|
||||
MIDI_TONE_MAX = MI_B_5,
|
||||
#elif MIDI_TONE_KEYCODE_OCTAVES > 4
|
||||
MIDI_TONE_MAX = MI_B_4,
|
||||
#elif MIDI_TONE_KEYCODE_OCTAVES > 3
|
||||
MIDI_TONE_MAX = MI_B_3,
|
||||
#elif MIDI_TONE_KEYCODE_OCTAVES > 2
|
||||
MIDI_TONE_MAX = MI_B_2,
|
||||
#elif MIDI_TONE_KEYCODE_OCTAVES > 1
|
||||
MIDI_TONE_MAX = MI_B_1,
|
||||
#elif MIDI_TONE_KEYCODE_OCTAVES > 0
|
||||
MIDI_TONE_MAX = MI_B,
|
||||
#endif
|
||||
|
||||
MIDI_OCTAVE_MIN,
|
||||
MI_OCT_N2 = MIDI_OCTAVE_MIN,
|
||||
MI_OCT_N1,
|
||||
MI_OCT_0,
|
||||
MI_OCT_1,
|
||||
MI_OCT_2,
|
||||
MI_OCT_3,
|
||||
MI_OCT_4,
|
||||
MI_OCT_5,
|
||||
MI_OCT_6,
|
||||
MI_OCT_7,
|
||||
MIDI_OCTAVE_MAX = MI_OCT_7,
|
||||
MI_OCTD, // octave down
|
||||
MI_OCTU, // octave up
|
||||
|
||||
MIDI_TRANSPOSE_MIN,
|
||||
MI_TRNS_N6 = MIDI_TRANSPOSE_MIN,
|
||||
MI_TRNS_N5,
|
||||
MI_TRNS_N4,
|
||||
MI_TRNS_N3,
|
||||
MI_TRNS_N2,
|
||||
MI_TRNS_N1,
|
||||
MI_TRNS_0,
|
||||
MI_TRNS_1,
|
||||
MI_TRNS_2,
|
||||
MI_TRNS_3,
|
||||
MI_TRNS_4,
|
||||
MI_TRNS_5,
|
||||
MI_TRNS_6,
|
||||
MIDI_TRANSPOSE_MAX = MI_TRNS_6,
|
||||
MI_TRNSD, // transpose down
|
||||
MI_TRNSU, // transpose up
|
||||
|
||||
MIDI_VELOCITY_MIN,
|
||||
MI_VEL_1 = MIDI_VELOCITY_MIN,
|
||||
MI_VEL_2,
|
||||
MI_VEL_3,
|
||||
MI_VEL_4,
|
||||
MI_VEL_5,
|
||||
MI_VEL_6,
|
||||
MI_VEL_7,
|
||||
MI_VEL_8,
|
||||
MI_VEL_9,
|
||||
MI_VEL_10,
|
||||
MIDI_VELOCITY_MAX = MI_VEL_10,
|
||||
MI_VELD, // velocity down
|
||||
MI_VELU, // velocity up
|
||||
|
||||
MIDI_CHANNEL_MIN,
|
||||
MI_CH1 = MIDI_CHANNEL_MIN,
|
||||
MI_CH2,
|
||||
MI_CH3,
|
||||
MI_CH4,
|
||||
MI_CH5,
|
||||
MI_CH6,
|
||||
MI_CH7,
|
||||
MI_CH8,
|
||||
MI_CH9,
|
||||
MI_CH10,
|
||||
MI_CH11,
|
||||
MI_CH12,
|
||||
MI_CH13,
|
||||
MI_CH14,
|
||||
MI_CH15,
|
||||
MI_CH16,
|
||||
MIDI_CHANNEL_MAX = MI_CH16,
|
||||
MI_CHD, // previous channel
|
||||
MI_CHU, // next channel
|
||||
|
||||
MI_ALLOFF, // all notes off
|
||||
|
||||
MI_SUS, // sustain
|
||||
MI_PORT, // portamento
|
||||
MI_SOST, // sostenuto
|
||||
MI_SOFT, // soft pedal
|
||||
MI_LEG, // legato
|
||||
|
||||
MI_MOD, // modulation
|
||||
MI_MODSD, // decrease modulation speed
|
||||
MI_MODSU, // increase modulation speed
|
||||
#endif // MIDI_ADVANCED
|
||||
|
||||
// Backlight functionality
|
||||
BL_0,
|
||||
BL_1,
|
||||
BL_2,
|
||||
BL_3,
|
||||
BL_4,
|
||||
BL_5,
|
||||
BL_6,
|
||||
BL_7,
|
||||
BL_8,
|
||||
BL_9,
|
||||
BL_10,
|
||||
BL_11,
|
||||
BL_12,
|
||||
BL_13,
|
||||
BL_14,
|
||||
BL_15,
|
||||
BL_DEC,
|
||||
BL_INC,
|
||||
BL_TOGG,
|
||||
BL_STEP,
|
||||
|
||||
// RGB functionality
|
||||
RGB_TOG,
|
||||
RGB_MOD,
|
||||
RGB_HUI,
|
||||
RGB_HUD,
|
||||
RGB_SAI,
|
||||
RGB_SAD,
|
||||
RGB_VAI,
|
||||
RGB_VAD,
|
||||
|
||||
// Left shift, open paren
|
||||
KC_LSPO,
|
||||
|
||||
// Right shift, close paren
|
||||
KC_RSPC,
|
||||
|
||||
// Printing
|
||||
PRINT_ON,
|
||||
PRINT_OFF,
|
||||
|
||||
// output selection
|
||||
OUT_AUTO,
|
||||
OUT_USB,
|
||||
#ifdef BLUETOOTH_ENABLE
|
||||
OUT_BT,
|
||||
#endif
|
||||
|
||||
// always leave at the end
|
||||
SAFE_RANGE
|
||||
};
|
||||
|
||||
// Ability to use mods in layouts
|
||||
#define LCTL(kc) (kc | QK_LCTL)
|
||||
#define LSFT(kc) (kc | QK_LSFT)
|
||||
#define LALT(kc) (kc | QK_LALT)
|
||||
#define LGUI(kc) (kc | QK_LGUI)
|
||||
#define RCTL(kc) (kc | QK_RCTL)
|
||||
#define RSFT(kc) (kc | QK_RSFT)
|
||||
#define RALT(kc) (kc | QK_RALT)
|
||||
#define RGUI(kc) (kc | QK_RGUI)
|
||||
|
||||
#define HYPR(kc) (kc | QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI)
|
||||
#define MEH(kc) (kc | QK_LCTL | QK_LSFT | QK_LALT)
|
||||
#define LCAG(kc) (kc | QK_LCTL | QK_LALT | QK_LGUI)
|
||||
#define ALTG(kc) (kc | QK_RCTL | QK_RALT)
|
||||
#define SCMD(kc) (kc | QK_LGUI | QK_LSFT)
|
||||
#define SWIN(kc) SCMD(kc)
|
||||
#define LCA(kc) (kc | QK_LCTL | QK_LALT)
|
||||
|
||||
#define MOD_HYPR 0xf
|
||||
#define MOD_MEH 0x7
|
||||
|
||||
|
||||
// Aliases for shifted symbols
|
||||
// Each key has a 4-letter code, and some have longer aliases too.
|
||||
// While the long aliases are descriptive, the 4-letter codes
|
||||
// make for nicer grid layouts (everything lines up), and are
|
||||
// the preferred style for Quantum.
|
||||
#define KC_TILD LSFT(KC_GRV) // ~
|
||||
#define KC_TILDE KC_TILD
|
||||
|
||||
#define KC_EXLM LSFT(KC_1) // !
|
||||
#define KC_EXCLAIM KC_EXLM
|
||||
|
||||
#define KC_AT LSFT(KC_2) // @
|
||||
|
||||
#define KC_HASH LSFT(KC_3) // #
|
||||
|
||||
#define KC_DLR LSFT(KC_4) // $
|
||||
#define KC_DOLLAR KC_DLR
|
||||
|
||||
#define KC_PERC LSFT(KC_5) // %
|
||||
#define KC_PERCENT KC_PERC
|
||||
|
||||
#define KC_CIRC LSFT(KC_6) // ^
|
||||
#define KC_CIRCUMFLEX KC_CIRC
|
||||
|
||||
#define KC_AMPR LSFT(KC_7) // &
|
||||
#define KC_AMPERSAND KC_AMPR
|
||||
|
||||
#define KC_ASTR LSFT(KC_8) // *
|
||||
#define KC_ASTERISK KC_ASTR
|
||||
|
||||
#define KC_LPRN LSFT(KC_9) // (
|
||||
#define KC_LEFT_PAREN KC_LPRN
|
||||
|
||||
#define KC_RPRN LSFT(KC_0) // )
|
||||
#define KC_RIGHT_PAREN KC_RPRN
|
||||
|
||||
#define KC_UNDS LSFT(KC_MINS) // _
|
||||
#define KC_UNDERSCORE KC_UNDS
|
||||
|
||||
#define KC_PLUS LSFT(KC_EQL) // +
|
||||
|
||||
#define KC_LCBR LSFT(KC_LBRC) // {
|
||||
#define KC_LEFT_CURLY_BRACE KC_LCBR
|
||||
|
||||
#define KC_RCBR LSFT(KC_RBRC) // }
|
||||
#define KC_RIGHT_CURLY_BRACE KC_RCBR
|
||||
|
||||
#define KC_LABK LSFT(KC_COMM) // <
|
||||
#define KC_LEFT_ANGLE_BRACKET KC_LABK
|
||||
|
||||
#define KC_RABK LSFT(KC_DOT) // >
|
||||
#define KC_RIGHT_ANGLE_BRACKET KC_RABK
|
||||
|
||||
#define KC_COLN LSFT(KC_SCLN) // :
|
||||
#define KC_COLON KC_COLN
|
||||
|
||||
#define KC_PIPE LSFT(KC_BSLS) // |
|
||||
|
||||
#define KC_LT LSFT(KC_COMM) // <
|
||||
|
||||
#define KC_GT LSFT(KC_DOT) // >
|
||||
|
||||
#define KC_QUES LSFT(KC_SLSH) // ?
|
||||
#define KC_QUESTION KC_QUES
|
||||
|
||||
#define KC_DQT LSFT(KC_QUOT) // "
|
||||
#define KC_DOUBLE_QUOTE KC_DQT
|
||||
#define KC_DQUO KC_DQT
|
||||
|
||||
#define KC_DELT KC_DELETE // Del key (four letter code)
|
||||
|
||||
// Alias for function layers than expand past FN31
|
||||
#define FUNC(kc) (kc | QK_FUNCTION)
|
||||
|
||||
// Aliases
|
||||
#define S(kc) LSFT(kc)
|
||||
#define F(kc) FUNC(kc)
|
||||
|
||||
#define M(kc) (kc | QK_MACRO)
|
||||
|
||||
#define MACROTAP(kc) (kc | QK_MACRO | FUNC_TAP<<8)
|
||||
#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
|
||||
|
||||
|
||||
// L-ayer, T-ap - 256 keycode max, 16 layer max
|
||||
#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
|
||||
|
||||
#define AG_SWAP MAGIC_SWAP_ALT_GUI
|
||||
#define AG_NORM MAGIC_UNSWAP_ALT_GUI
|
||||
|
||||
#define BL_ON BL_9
|
||||
#define BL_OFF BL_0
|
||||
|
||||
// GOTO layer - 16 layers max
|
||||
// when:
|
||||
// ON_PRESS = 1
|
||||
// ON_RELEASE = 2
|
||||
// Unless you have a good reason not to do so, prefer ON_PRESS (1) as your default.
|
||||
// In fact, we changed it to assume ON_PRESS for sanity/simplicity. If needed, you can add your own
|
||||
// keycode modeled after the old version, kept below for this.
|
||||
/* #define TO(layer, when) (layer | QK_TO | (when << 0x4)) */
|
||||
#define TO(layer) (layer | QK_TO | (ON_PRESS << 0x4))
|
||||
|
||||
// Momentary switch layer - 256 layer max
|
||||
#define MO(layer) (layer | QK_MOMENTARY)
|
||||
|
||||
// Set default layer - 256 layer max
|
||||
#define DF(layer) (layer | QK_DEF_LAYER)
|
||||
|
||||
// Toggle to layer - 256 layer max
|
||||
#define TG(layer) (layer | QK_TOGGLE_LAYER)
|
||||
|
||||
// One-shot layer - 256 layer max
|
||||
#define OSL(layer) (layer | QK_ONE_SHOT_LAYER)
|
||||
|
||||
// One-shot mod
|
||||
#define OSM(mod) (mod | QK_ONE_SHOT_MOD)
|
||||
|
||||
// Layer tap-toggle
|
||||
#define TT(layer) (layer | QK_LAYER_TAP_TOGGLE)
|
||||
|
||||
// M-od, T-ap - 256 keycode max
|
||||
#define MT(mod, kc) (kc | QK_MOD_TAP | ((mod & 0x1F) << 8))
|
||||
|
||||
#define CTL_T(kc) MT(MOD_LCTL, kc)
|
||||
#define LCTL_T(kc) MT(MOD_LCTL, kc)
|
||||
#define RCTL_T(kc) MT(MOD_RCTL, kc)
|
||||
|
||||
#define SFT_T(kc) MT(MOD_LSFT, kc)
|
||||
#define LSFT_T(kc) MT(MOD_LSFT, kc)
|
||||
#define RSFT_T(kc) MT(MOD_RSFT, kc)
|
||||
|
||||
#define ALT_T(kc) MT(MOD_LALT, kc)
|
||||
#define LALT_T(kc) MT(MOD_LALT, kc)
|
||||
#define RALT_T(kc) MT(MOD_RALT, kc)
|
||||
#define ALGR_T(kc) MT(MOD_RALT, kc) // dual-function AltGR
|
||||
|
||||
#define GUI_T(kc) MT(MOD_LGUI, kc)
|
||||
#define LGUI_T(kc) MT(MOD_LGUI, kc)
|
||||
#define RGUI_T(kc) MT(MOD_RGUI, kc)
|
||||
|
||||
#define C_S_T(kc) MT((MOD_LCTL | MOD_LSFT), kc) // Control + Shift e.g. for gnome-terminal
|
||||
#define MEH_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT), kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl
|
||||
#define LCAG_T(kc) MT((MOD_LCTL | MOD_LALT | MOD_LGUI), kc) // Left control alt and gui
|
||||
#define RCAG_T(kc) MT((MOD_RCTL | MOD_RALT | MOD_RGUI), kc) // Right control alt and gui
|
||||
#define ALL_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI), kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
|
||||
#define SCMD_T(kc) MT((MOD_LGUI | MOD_LSFT), kc)
|
||||
#define SWIN_T(kc) SCMD_T(kc)
|
||||
#define LCA_T(kc) MT((MOD_LCTL | MOD_LALT), kc) // Left control and left alt
|
||||
|
||||
// Dedicated keycode versions for Hyper and Meh, if you want to use them as standalone keys rather than mod-tap
|
||||
#define KC_HYPR HYPR(KC_NO)
|
||||
#define KC_MEH MEH(KC_NO)
|
||||
|
||||
#ifdef UNICODE_ENABLE
|
||||
// For sending unicode codes.
|
||||
// You may not send codes over 7FFF -- this supports most of UTF8.
|
||||
// To have a key that sends out Œ, go UC(0x0152)
|
||||
#define UNICODE(n) (n | QK_UNICODE)
|
||||
#define UC(n) UNICODE(n)
|
||||
#endif
|
||||
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
#define X(n) (n | QK_UNICODE_MAP)
|
||||
#endif
|
||||
|
||||
#endif // QUANTUM_KEYCODES_H
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2016-2017 Yang Liu
|
||||
*
|
||||
* 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 <avr/eeprom.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
|
@ -66,14 +81,17 @@ __attribute__ ((weak))
|
|||
const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
|
||||
__attribute__ ((weak))
|
||||
const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {100, 50, 20};
|
||||
__attribute__ ((weak))
|
||||
const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90};
|
||||
|
||||
rgblight_config_t rgblight_config;
|
||||
rgblight_config_t inmem_config;
|
||||
struct cRGB led[RGBLED_NUM];
|
||||
|
||||
LED_TYPE led[RGBLED_NUM];
|
||||
uint8_t rgblight_inited = 0;
|
||||
bool rgblight_timer_enabled = false;
|
||||
|
||||
|
||||
void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) {
|
||||
void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
|
||||
uint8_t r = 0, g = 0, b = 0, base, color;
|
||||
|
||||
if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
|
||||
|
@ -124,7 +142,7 @@ void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) {
|
|||
setrgb(r, g, b, led1);
|
||||
}
|
||||
|
||||
void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1) {
|
||||
void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
|
||||
(*led1).r = r;
|
||||
(*led1).g = g;
|
||||
(*led1).b = b;
|
||||
|
@ -141,9 +159,9 @@ void eeconfig_update_rgblight_default(void) {
|
|||
dprintf("eeconfig_update_rgblight_default\n");
|
||||
rgblight_config.enable = 1;
|
||||
rgblight_config.mode = 1;
|
||||
rgblight_config.hue = 200;
|
||||
rgblight_config.sat = 204;
|
||||
rgblight_config.val = 204;
|
||||
rgblight_config.hue = 0;
|
||||
rgblight_config.sat = 255;
|
||||
rgblight_config.val = 255;
|
||||
eeconfig_update_rgblight(rgblight_config.raw);
|
||||
}
|
||||
void eeconfig_debug_rgblight(void) {
|
||||
|
@ -173,7 +191,7 @@ void rgblight_init(void) {
|
|||
}
|
||||
eeconfig_debug_rgblight(); // display current eeprom values
|
||||
|
||||
#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
rgblight_timer_init(); // setup the timer
|
||||
#endif
|
||||
|
||||
|
@ -182,6 +200,19 @@ void rgblight_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void rgblight_update_dword(uint32_t dword) {
|
||||
rgblight_config.raw = dword;
|
||||
eeconfig_update_rgblight(rgblight_config.raw);
|
||||
if (rgblight_config.enable)
|
||||
rgblight_mode(rgblight_config.mode);
|
||||
else {
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
rgblight_timer_disable();
|
||||
#endif
|
||||
rgblight_set();
|
||||
}
|
||||
}
|
||||
|
||||
void rgblight_increase(void) {
|
||||
uint8_t mode = 0;
|
||||
if (rgblight_config.mode < RGBLIGHT_MODES) {
|
||||
|
@ -205,6 +236,14 @@ void rgblight_step(void) {
|
|||
}
|
||||
rgblight_mode(mode);
|
||||
}
|
||||
void rgblight_step_reverse(void) {
|
||||
uint8_t mode = 0;
|
||||
mode = rgblight_config.mode - 1;
|
||||
if (mode < 1) {
|
||||
mode = RGBLIGHT_MODES;
|
||||
}
|
||||
rgblight_mode(mode);
|
||||
}
|
||||
|
||||
void rgblight_mode(uint8_t mode) {
|
||||
if (!rgblight_config.enable) {
|
||||
|
@ -220,19 +259,25 @@ void rgblight_mode(uint8_t mode) {
|
|||
eeconfig_update_rgblight(rgblight_config.raw);
|
||||
xprintf("rgblight mode: %u\n", rgblight_config.mode);
|
||||
if (rgblight_config.mode == 1) {
|
||||
#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
rgblight_timer_disable();
|
||||
#endif
|
||||
} else if (rgblight_config.mode >= 2 && rgblight_config.mode <= 23) {
|
||||
} else if (rgblight_config.mode >= 2 && rgblight_config.mode <= 24) {
|
||||
// MODE 2-5, breathing
|
||||
// MODE 6-8, rainbow mood
|
||||
// MODE 9-14, rainbow swirl
|
||||
// MODE 15-20, snake
|
||||
// MODE 21-23, knight
|
||||
|
||||
#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
rgblight_timer_enable();
|
||||
#endif
|
||||
} else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
|
||||
// MODE 25-34, static gradient
|
||||
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
rgblight_timer_disable();
|
||||
#endif
|
||||
}
|
||||
rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
|
||||
}
|
||||
|
@ -244,7 +289,7 @@ void rgblight_toggle(void) {
|
|||
if (rgblight_config.enable) {
|
||||
rgblight_mode(rgblight_config.mode);
|
||||
} else {
|
||||
#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
rgblight_timer_disable();
|
||||
#endif
|
||||
_delay_ms(50);
|
||||
|
@ -252,6 +297,13 @@ void rgblight_toggle(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void rgblight_enable(void) {
|
||||
rgblight_config.enable = 1;
|
||||
eeconfig_update_rgblight(rgblight_config.raw);
|
||||
xprintf("rgblight enable: rgblight_config.enable = %u\n", rgblight_config.enable);
|
||||
rgblight_mode(rgblight_config.mode);
|
||||
}
|
||||
|
||||
|
||||
void rgblight_increase_hue(void) {
|
||||
uint16_t hue;
|
||||
|
@ -307,7 +359,7 @@ void rgblight_decrease_val(void) {
|
|||
void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
|
||||
inmem_config.raw = rgblight_config.raw;
|
||||
if (rgblight_config.enable) {
|
||||
struct cRGB tmp_led;
|
||||
LED_TYPE tmp_led;
|
||||
sethsv(hue, sat, val, &tmp_led);
|
||||
inmem_config.hue = hue;
|
||||
inmem_config.sat = sat;
|
||||
|
@ -329,6 +381,17 @@ void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
|
|||
} else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) {
|
||||
// rainbow mood and rainbow swirl, ignore the change of hue
|
||||
hue = rgblight_config.hue;
|
||||
} else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
|
||||
// static gradient
|
||||
uint16_t _hue;
|
||||
int8_t direction = ((rgblight_config.mode - 25) % 2) ? -1 : 1;
|
||||
uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[(rgblight_config.mode - 25) / 2]);
|
||||
for (uint8_t i = 0; i < RGBLED_NUM; i++) {
|
||||
_hue = (range / RGBLED_NUM * i * direction + hue + 360) % 360;
|
||||
dprintf("rgblight rainbow set hsv: %u,%u,%d,%u\n", i, _hue, direction, range);
|
||||
sethsv(_hue, sat, val, (LED_TYPE *)&led[i]);
|
||||
}
|
||||
rgblight_set();
|
||||
}
|
||||
}
|
||||
rgblight_config.hue = hue;
|
||||
|
@ -349,68 +412,90 @@ void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
|
|||
rgblight_set();
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void rgblight_set(void) {
|
||||
if (rgblight_config.enable) {
|
||||
ws2812_setleds(led, RGBLED_NUM);
|
||||
#ifdef RGBW
|
||||
ws2812_setleds_rgbw(led, RGBLED_NUM);
|
||||
#else
|
||||
ws2812_setleds(led, RGBLED_NUM);
|
||||
#endif
|
||||
} else {
|
||||
for (uint8_t i = 0; i < RGBLED_NUM; i++) {
|
||||
led[i].r = 0;
|
||||
led[i].g = 0;
|
||||
led[i].b = 0;
|
||||
}
|
||||
ws2812_setleds(led, RGBLED_NUM);
|
||||
#ifdef RGBW
|
||||
ws2812_setleds_rgbw(led, RGBLED_NUM);
|
||||
#else
|
||||
ws2812_setleds(led, RGBLED_NUM);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
|
||||
// Animation timer -- AVR Timer3
|
||||
void rgblight_timer_init(void) {
|
||||
static uint8_t rgblight_timer_is_init = 0;
|
||||
if (rgblight_timer_is_init) {
|
||||
return;
|
||||
}
|
||||
rgblight_timer_is_init = 1;
|
||||
/* Timer 3 setup */
|
||||
TCCR3B = _BV(WGM32) //CTC mode OCR3A as TOP
|
||||
| _BV(CS30); //Clock selelct: clk/1
|
||||
/* Set TOP value */
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
|
||||
OCR3AL = RGBLED_TIMER_TOP & 0xff;
|
||||
SREG = sreg;
|
||||
// static uint8_t rgblight_timer_is_init = 0;
|
||||
// if (rgblight_timer_is_init) {
|
||||
// return;
|
||||
// }
|
||||
// rgblight_timer_is_init = 1;
|
||||
// /* Timer 3 setup */
|
||||
// TCCR3B = _BV(WGM32) // CTC mode OCR3A as TOP
|
||||
// | _BV(CS30); // Clock selelct: clk/1
|
||||
// /* Set TOP value */
|
||||
// uint8_t sreg = SREG;
|
||||
// cli();
|
||||
// OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
|
||||
// OCR3AL = RGBLED_TIMER_TOP & 0xff;
|
||||
// SREG = sreg;
|
||||
|
||||
rgblight_timer_enabled = true;
|
||||
}
|
||||
void rgblight_timer_enable(void) {
|
||||
TIMSK3 |= _BV(OCIE3A);
|
||||
rgblight_timer_enabled = true;
|
||||
dprintf("TIMER3 enabled.\n");
|
||||
}
|
||||
void rgblight_timer_disable(void) {
|
||||
TIMSK3 &= ~_BV(OCIE3A);
|
||||
rgblight_timer_enabled = false;
|
||||
dprintf("TIMER3 disabled.\n");
|
||||
}
|
||||
void rgblight_timer_toggle(void) {
|
||||
TIMSK3 ^= _BV(OCIE3A);
|
||||
rgblight_timer_enabled ^= rgblight_timer_enabled;
|
||||
dprintf("TIMER3 toggled.\n");
|
||||
}
|
||||
|
||||
ISR(TIMER3_COMPA_vect) {
|
||||
// mode = 1, static light, do nothing here
|
||||
if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
|
||||
// mode = 2 to 5, breathing mode
|
||||
rgblight_effect_breathing(rgblight_config.mode - 2);
|
||||
} else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) {
|
||||
// mode = 6 to 8, rainbow mood mod
|
||||
rgblight_effect_rainbow_mood(rgblight_config.mode - 6);
|
||||
} else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) {
|
||||
// mode = 9 to 14, rainbow swirl mode
|
||||
rgblight_effect_rainbow_swirl(rgblight_config.mode - 9);
|
||||
} else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) {
|
||||
// mode = 15 to 20, snake mode
|
||||
rgblight_effect_snake(rgblight_config.mode - 15);
|
||||
} else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
|
||||
// mode = 21 to 23, knight mode
|
||||
rgblight_effect_knight(rgblight_config.mode - 21);
|
||||
void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
|
||||
rgblight_enable();
|
||||
rgblight_mode(1);
|
||||
rgblight_setrgb(r, g, b);
|
||||
}
|
||||
|
||||
void rgblight_task(void) {
|
||||
if (rgblight_timer_enabled) {
|
||||
// mode = 1, static light, do nothing here
|
||||
if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
|
||||
// mode = 2 to 5, breathing mode
|
||||
rgblight_effect_breathing(rgblight_config.mode - 2);
|
||||
} else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) {
|
||||
// mode = 6 to 8, rainbow mood mod
|
||||
rgblight_effect_rainbow_mood(rgblight_config.mode - 6);
|
||||
} else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) {
|
||||
// mode = 9 to 14, rainbow swirl mode
|
||||
rgblight_effect_rainbow_swirl(rgblight_config.mode - 9);
|
||||
} else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) {
|
||||
// mode = 15 to 20, snake mode
|
||||
rgblight_effect_snake(rgblight_config.mode - 15);
|
||||
} else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
|
||||
// mode = 21 to 23, knight mode
|
||||
rgblight_effect_knight(rgblight_config.mode - 21);
|
||||
} else if (rgblight_config.mode == 24) {
|
||||
// mode = 24, christmas mode
|
||||
rgblight_effect_christmas();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,7 +534,7 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) {
|
|||
last_timer = timer_read();
|
||||
for (i = 0; i < RGBLED_NUM; i++) {
|
||||
hue = (360 / RGBLED_NUM * i + current_hue) % 360;
|
||||
sethsv(hue, rgblight_config.sat, rgblight_config.val, &led[i]);
|
||||
sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
|
||||
}
|
||||
rgblight_set();
|
||||
|
||||
|
@ -486,7 +571,7 @@ void rgblight_effect_snake(uint8_t interval) {
|
|||
k = k + RGBLED_NUM;
|
||||
}
|
||||
if (i == k) {
|
||||
sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), &led[i]);
|
||||
sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), (LED_TYPE *)&led[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -506,7 +591,7 @@ void rgblight_effect_knight(uint8_t interval) {
|
|||
static uint16_t last_timer = 0;
|
||||
uint8_t i, j, cur;
|
||||
int8_t k;
|
||||
struct cRGB preled[RGBLED_NUM];
|
||||
LED_TYPE preled[RGBLED_NUM];
|
||||
static int8_t increment = -1;
|
||||
if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) {
|
||||
return;
|
||||
|
@ -525,7 +610,7 @@ void rgblight_effect_knight(uint8_t interval) {
|
|||
k = RGBLED_NUM - 1;
|
||||
}
|
||||
if (i == k) {
|
||||
sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, &preled[i]);
|
||||
sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&preled[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -555,4 +640,22 @@ void rgblight_effect_knight(uint8_t interval) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void rgblight_effect_christmas(void) {
|
||||
static uint16_t current_offset = 0;
|
||||
static uint16_t last_timer = 0;
|
||||
uint16_t hue;
|
||||
uint8_t i;
|
||||
if (timer_elapsed(last_timer) < RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL) {
|
||||
return;
|
||||
}
|
||||
last_timer = timer_read();
|
||||
current_offset = (current_offset + 1) % 2;
|
||||
for (i = 0; i < RGBLED_NUM; i++) {
|
||||
hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + current_offset) % 2) * 120;
|
||||
sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
|
||||
}
|
||||
rgblight_set();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
/* Copyright 2017 Yang Liu
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef RGBLIGHT_H
|
||||
#define RGBLIGHT_H
|
||||
|
||||
|
||||
#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
|
||||
#define RGBLIGHT_MODES 23
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
#define RGBLIGHT_MODES 34
|
||||
#else
|
||||
#define RGBLIGHT_MODES 1
|
||||
#endif
|
||||
|
@ -23,6 +37,14 @@
|
|||
#define RGBLIGHT_EFFECT_DUALKNIGHT_LENGTH 4
|
||||
#endif
|
||||
|
||||
#ifndef RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL
|
||||
#define RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL 1000
|
||||
#endif
|
||||
|
||||
#ifndef RGBLIGHT_EFFECT_CHRISTMAS_STEP
|
||||
#define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2
|
||||
#endif
|
||||
|
||||
#ifndef RGBLIGHT_HUE_STEP
|
||||
#define RGBLIGHT_HUE_STEP 10
|
||||
#endif
|
||||
|
@ -34,12 +56,15 @@
|
|||
#endif
|
||||
|
||||
#define RGBLED_TIMER_TOP F_CPU/(256*64)
|
||||
// #define RGBLED_TIMER_TOP 0xFF10
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "eeconfig.h"
|
||||
#include "light_ws2812.h"
|
||||
|
||||
extern LED_TYPE led[RGBLED_NUM];
|
||||
|
||||
extern const uint8_t RGBLED_BREATHING_INTERVALS[4] PROGMEM;
|
||||
extern const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[3] PROGMEM;
|
||||
extern const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[3] PROGMEM;
|
||||
|
@ -61,9 +86,12 @@ void rgblight_init(void);
|
|||
void rgblight_increase(void);
|
||||
void rgblight_decrease(void);
|
||||
void rgblight_toggle(void);
|
||||
void rgblight_enable(void);
|
||||
void rgblight_step(void);
|
||||
void rgblight_step_reverse(void);
|
||||
void rgblight_mode(uint8_t mode);
|
||||
void rgblight_set(void);
|
||||
void rgblight_update_dword(uint32_t dword);
|
||||
void rgblight_increase_hue(void);
|
||||
void rgblight_decrease_hue(void);
|
||||
void rgblight_increase_sat(void);
|
||||
|
@ -78,10 +106,15 @@ void eeconfig_update_rgblight(uint32_t val);
|
|||
void eeconfig_update_rgblight_default(void);
|
||||
void eeconfig_debug_rgblight(void);
|
||||
|
||||
void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1);
|
||||
void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1);
|
||||
void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1);
|
||||
void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1);
|
||||
void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);
|
||||
|
||||
#define EZ_RGB(val) rgblight_show_solid_color((val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF)
|
||||
void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
void rgblight_task(void);
|
||||
|
||||
void rgblight_timer_init(void);
|
||||
void rgblight_timer_enable(void);
|
||||
void rgblight_timer_disable(void);
|
||||
|
@ -91,5 +124,6 @@ void rgblight_effect_rainbow_mood(uint8_t interval);
|
|||
void rgblight_effect_rainbow_swirl(uint8_t interval);
|
||||
void rgblight_effect_snake(uint8_t interval);
|
||||
void rgblight_effect_knight(uint8_t interval);
|
||||
void rgblight_effect_christmas(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Fred Sundvik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
# Copyright 2013 Jun Wako <wakojun@gmail.com>
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
ifndef MAKEFILE_INCLUDED
|
||||
include ../../Makefile
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
Copyright 2017 REPLACE_WITH_YOUR_NAME
|
||||
|
||||
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
|
||||
|
@ -46,7 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define MATRIX_COL_PINS { F1, F0, B0 }
|
||||
#define UNUSED_PINS
|
||||
|
||||
/* COL2ROW or ROW2COL */
|
||||
/* COL2ROW, ROW2COL, or CUSTOM_MATRIX */
|
||||
#define DIODE_DIRECTION COL2ROW
|
||||
|
||||
// #define BACKLIGHT_PIN B7
|
||||
|
@ -159,4 +159,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
//#define NO_ACTION_MACRO
|
||||
//#define NO_ACTION_FUNCTION
|
||||
|
||||
/*
|
||||
* MIDI options
|
||||
*/
|
||||
|
||||
/* Prevent use of disabled MIDI features in the keymap */
|
||||
//#define MIDI_ENABLE_STRICT 1
|
||||
|
||||
/* enable basic MIDI features:
|
||||
- MIDI notes can be sent when in Music mode is on
|
||||
*/
|
||||
//#define MIDI_BASIC
|
||||
|
||||
/* enable advanced MIDI features:
|
||||
- MIDI notes can be added to the keymap
|
||||
- Octave shift and transpose
|
||||
- Virtual sustain, portamento, and modulation wheel
|
||||
- etc.
|
||||
*/
|
||||
//#define MIDI_ADVANCED
|
||||
|
||||
/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
|
||||
//#define MIDI_TONE_KEYCODE_OCTAVES 1
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
# Build Options
|
||||
# Copyright 2013 Jun Wako <wakojun@gmail.com>
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
|
||||
# QMK Build Options
|
||||
# change to "no" to disable the options, or define them in the Makefile in
|
||||
# the appropriate keymap folder that will get included automatically
|
||||
#
|
||||
|
@ -9,7 +25,7 @@ CONSOLE_ENABLE = no # Console for debug(+400)
|
|||
COMMAND_ENABLE = yes # Commands for debug and configuration
|
||||
NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
|
||||
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
|
||||
MIDI_ENABLE = no # MIDI controls
|
||||
MIDI_ENABLE = no # MIDI support (+2400 to 4200, depending on config)
|
||||
AUDIO_ENABLE = no # Audio output on port C6
|
||||
UNICODE_ENABLE = no # Unicode
|
||||
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
|
||||
|
@ -18,4 +34,4 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
|||
|
||||
ifndef QUANTUM_DIR
|
||||
include ../../../../Makefile
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2017 REPLACE_WITH_YOUR_NAME
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USER_H
|
||||
#define CONFIG_USER_H
|
||||
|
||||
|
@ -5,4 +21,4 @@
|
|||
|
||||
// place overrides here
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2017 REPLACE_WITH_YOUR_NAME
|
||||
*
|
||||
* 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 "%KEYBOARD%.h"
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
@ -41,4 +56,4 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|||
|
||||
void led_set_user(uint8_t usb_led) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,8 @@ SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
|
|||
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
|
||||
NKRO_ENABLE ?= no # USB Nkey Rollover
|
||||
BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default
|
||||
MIDI_ENABLE ?= no # MIDI controls
|
||||
MIDI_ENABLE ?= no # MIDI support (+2400 to 4200, depending on config)
|
||||
UNICODE_ENABLE ?= no # Unicode
|
||||
BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
|
||||
AUDIO_ENABLE ?= no # Audio output on port C6
|
||||
FAUXCLICKY_ENABLE ?= no # Use buzzer to emulate clicky switches
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2017 REPLACE_WITH_YOUR_NAME
|
||||
*
|
||||
* 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 "%KEYBOARD%.h"
|
||||
|
||||
void matrix_init_kb(void) {
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/* Copyright 2017 REPLACE_WITH_YOUR_NAME
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef %KEYBOARD_UPPERCASE%_H
|
||||
#define %KEYBOARD_UPPERCASE%_H
|
||||
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 Fred Sundvik
|
||||
*
|
||||
* 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 "variable_trace.h"
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/* Copyright 2016 Fred Sundvik
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef VARIABLE_TRACE_H
|
||||
#define VARIABLE_TRACE_H
|
||||
|
||||
|
|
|
@ -53,10 +53,13 @@ SOFTWARE.
|
|||
#define "Visualizer thread priority not defined"
|
||||
#endif
|
||||
|
||||
// mods status
|
||||
#include "action_util.h"
|
||||
|
||||
static visualizer_keyboard_status_t current_status = {
|
||||
.layer = 0xFFFFFFFF,
|
||||
.default_layer = 0xFFFFFFFF,
|
||||
.mods = 0xFF,
|
||||
.leds = 0xFFFFFFFF,
|
||||
.suspended = false,
|
||||
};
|
||||
|
@ -64,6 +67,7 @@ static visualizer_keyboard_status_t current_status = {
|
|||
static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) {
|
||||
return status1->layer == status2->layer &&
|
||||
status1->default_layer == status2->default_layer &&
|
||||
status1->mods == status2->mods &&
|
||||
status1->leds == status2->leds &&
|
||||
status1->suspended == status2->suspended;
|
||||
}
|
||||
|
@ -307,6 +311,45 @@ bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_s
|
|||
gdispFlush();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void format_mods_bitmap_string(uint8_t mods, char* buffer) {
|
||||
*buffer = ' ';
|
||||
++buffer;
|
||||
|
||||
for (int i = 0; i<8; i++)
|
||||
{
|
||||
uint32_t mask = (1u << i);
|
||||
if (mods & mask) {
|
||||
*buffer = '1';
|
||||
} else {
|
||||
*buffer = '0';
|
||||
}
|
||||
++buffer;
|
||||
|
||||
if (i==3) {
|
||||
*buffer = ' ';
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
*buffer = 0;
|
||||
}
|
||||
|
||||
bool keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) {
|
||||
(void)animation;
|
||||
|
||||
const char* title = "Modifier states";
|
||||
const char* mods_header = " CSAG CSAG ";
|
||||
char status_buffer[12];
|
||||
|
||||
gdispClear(White);
|
||||
gdispDrawString(0, 0, title, state->font_fixed5x8, Black);
|
||||
gdispDrawString(0, 10, mods_header, state->font_fixed5x8, Black);
|
||||
format_mods_bitmap_string(state->status.mods, status_buffer);
|
||||
gdispDrawString(0, 20, status_buffer, state->font_fixed5x8, Black);
|
||||
|
||||
gdispFlush();
|
||||
return false;
|
||||
}
|
||||
#endif // LCD_ENABLE
|
||||
|
||||
bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) {
|
||||
|
@ -350,6 +393,7 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
|
|||
visualizer_keyboard_status_t initial_status = {
|
||||
.default_layer = 0xFFFFFFFF,
|
||||
.layer = 0xFFFFFFFF,
|
||||
.mods = 0xFF,
|
||||
.leds = 0xFFFFFFFF,
|
||||
.suspended = false,
|
||||
};
|
||||
|
@ -499,7 +543,18 @@ void update_status(bool changed) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds) {
|
||||
uint8_t visualizer_get_mods() {
|
||||
uint8_t mods = get_mods();
|
||||
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
if (!has_oneshot_mods_timed_out()) {
|
||||
mods |= get_oneshot_mods();
|
||||
}
|
||||
#endif
|
||||
return mods;
|
||||
}
|
||||
|
||||
void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uint32_t leds) {
|
||||
// Note that there's a small race condition here, the thread could read
|
||||
// a state where one of these are set but not the other. But this should
|
||||
// not really matter as it will be fixed during the next loop step.
|
||||
|
@ -523,6 +578,7 @@ void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds) {
|
|||
visualizer_keyboard_status_t new_status = {
|
||||
.layer = state,
|
||||
.default_layer = default_state,
|
||||
.mods = mods,
|
||||
.leds = leds,
|
||||
.suspended = current_status.suspended,
|
||||
};
|
||||
|
|
|
@ -34,10 +34,14 @@ SOFTWARE.
|
|||
#include "lcd_backlight.h"
|
||||
#endif
|
||||
|
||||
// use this function to merget both real_mods and oneshot_mods in a uint16_t
|
||||
uint8_t visualizer_get_mods(void);
|
||||
|
||||
// This need to be called once at the start
|
||||
void visualizer_init(void);
|
||||
// This should be called at every matrix scan
|
||||
void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds);
|
||||
void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uint32_t leds);
|
||||
|
||||
// This should be called when the keyboard goes to suspend state
|
||||
void visualizer_suspend(void);
|
||||
// This should be called when the keyboard wakes up from suspend state
|
||||
|
@ -61,6 +65,7 @@ struct keyframe_animation_t;
|
|||
typedef struct {
|
||||
uint32_t layer;
|
||||
uint32_t default_layer;
|
||||
uint8_t mods;
|
||||
uint32_t leds; // See led.h for available statuses
|
||||
bool suspended;
|
||||
} visualizer_keyboard_status_t;
|
||||
|
@ -129,6 +134,8 @@ bool keyframe_set_backlight_color(keyframe_animation_t* animation, visualizer_st
|
|||
bool keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state);
|
||||
// Displays a bitmap (0/1) of all the currently active layers
|
||||
bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state);
|
||||
// Displays a bitmap (0/1) of all the currently active mods
|
||||
bool keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state);
|
||||
|
||||
bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state);
|
||||
bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue