@@ -8,3 +8,4 @@ | |||
*.map | |||
*.sym | |||
tags | |||
*.swp |
@@ -1,3 +1,6 @@ | |||
[submodule "protocol/usb_hid/USB_Host_Shield_2.0"] | |||
path = protocol/usb_hid/USB_Host_Shield_2.0 | |||
url = [email protected]:tmk/USB_Host_Shield_2.0.git | |||
[submodule "protocol/lufa/LUFA-git"] | |||
path = protocol/lufa/LUFA-git | |||
url = https://github.com/abcminiuser/lufa.git |
@@ -52,6 +52,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di | |||
* [IIgs_Standard](keyboard/IIgs/) - Apple [IIGS] keyboard mod(by JeffreySung) | |||
* [macway](keyboard/macway/) - [Compact keyboard mod][GH_macway] [retired] | |||
* [KMAC](keyboard/kmac/) - Korean custom keyboard | |||
* [Lightsaber](keyboard/lightsaber/) - Korean custom keyboard | |||
[GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930 | |||
[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047 |
@@ -22,7 +22,7 @@ ifdef BOOTMAGIC_ENABLE | |||
OPT_DEFS += -DBOOTMAGIC_ENABLE | |||
endif | |||
ifdef MOUSEKEY_ENABLE | |||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||
SRC += $(COMMON_DIR)/mousekey.c | |||
OPT_DEFS += -DMOUSEKEY_ENABLE | |||
OPT_DEFS += -DMOUSE_ENABLE | |||
@@ -54,6 +54,11 @@ ifdef SLEEP_LED_ENABLE | |||
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN | |||
endif | |||
ifdef BREATHING_LED_ENABLE | |||
SRC += $(COMMON_DIR)/breathing_led.c | |||
OPT_DEFS += -DBREATHING_LED_ENABLE | |||
endif | |||
ifdef BACKLIGHT_ENABLE | |||
SRC += $(COMMON_DIR)/backlight.c | |||
OPT_DEFS += -DBACKLIGHT_ENABLE | |||
@@ -69,6 +74,11 @@ ifdef KEYMAP_IN_EEPROM_ENABLE | |||
OPT_DEFS += -DKEYMAP_IN_EEPROM_ENABLE | |||
endif | |||
ifdef LED_MATRIX_ENABLE | |||
SRC += $(COMMON_DIR)/led_matrix.c | |||
OPT_DEFS += -DLED_MATRIX_ENABLE | |||
endif | |||
# Version string | |||
OPT_DEFS += -DVERSION=$(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null) | |||
@@ -294,7 +294,7 @@ void process_action(keyrecord_t *record) | |||
#ifdef BACKLIGHT_ENABLE | |||
case ACT_BACKLIGHT: | |||
if (!event.pressed) { | |||
switch (action.backlight.id) { | |||
switch (action.backlight.opt) { | |||
case BACKLIGHT_INCREASE: | |||
backlight_increase(); | |||
break; | |||
@@ -307,6 +307,9 @@ void process_action(keyrecord_t *record) | |||
case BACKLIGHT_STEP: | |||
backlight_step(); | |||
break; | |||
case BACKLIGHT_LEVEL: | |||
backlight_level(action.backlight.level); | |||
break; | |||
} | |||
} | |||
break; |
@@ -87,7 +87,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
* 1100|1111| id(8) Macro record? | |||
* | |||
* ACT_BACKLIGHT(1101): | |||
* 1101|xxxx| id(8) Backlight commands | |||
* 1101|opt |level(8) Backlight commands | |||
* | |||
* ACT_COMMAND(1110): | |||
* 1110|opt | id(8) Built-in Command exec | |||
@@ -163,7 +163,9 @@ typedef union { | |||
uint8_t kind :4; | |||
} usage; | |||
struct action_backlight { | |||
uint8_t id :8; | |||
uint8_t level :8; | |||
uint8_t opt :4; | |||
uint8_t kind :4; | |||
} backlight; | |||
struct action_command { | |||
uint8_t id :8; | |||
@@ -282,21 +284,23 @@ enum layer_pram_tap_op { | |||
/* | |||
* Extensions | |||
*/ | |||
enum backlight_id { | |||
enum backlight_opt { | |||
BACKLIGHT_INCREASE = 0, | |||
BACKLIGHT_DECREASE = 1, | |||
BACKLIGHT_TOGGLE = 2, | |||
BACKLIGHT_STEP = 3, | |||
BACKLIGHT_LEVEL = 4, | |||
}; | |||
/* Macro */ | |||
#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id)) | |||
#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP<<8 | (id)) | |||
#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt)<<8 | (id)) | |||
/* Backlight */ | |||
#define ACTION_BACKLIGHT_INCREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE) | |||
#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE) | |||
#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE) | |||
#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP) | |||
#define ACTION_BACKLIGHT_INCREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE << 8) | |||
#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8) | |||
#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8) | |||
#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8) | |||
#define ACTION_BACKLIGHT_LEVEL(level) ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | level) | |||
/* Command */ | |||
#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (addr)) | |||
/* Function */ |
@@ -33,6 +33,16 @@ void backlight_init(void) | |||
void backlight_increase(void) | |||
{ | |||
#ifdef BACKLIGHT_CUSTOM | |||
if (backlight_config.enable) { | |||
if (backlight_config.level < BACKLIGHT_LEVELS) { | |||
backlight_config.level++; | |||
eeconfig_write_backlight(backlight_config.raw); | |||
} | |||
dprintf("backlight custom increase: %u\n", backlight_config.level); | |||
backlight_set(backlight_config.level); | |||
} | |||
#else | |||
if(backlight_config.level < BACKLIGHT_LEVELS) | |||
{ | |||
backlight_config.level++; | |||
@@ -41,10 +51,22 @@ void backlight_increase(void) | |||
} | |||
dprintf("backlight increase: %u\n", backlight_config.level); | |||
backlight_set(backlight_config.level); | |||
#endif | |||
} | |||
void backlight_decrease(void) | |||
{ | |||
#ifdef BACKLIGHT_CUSTOM | |||
if (backlight_config.enable) { | |||
if(backlight_config.level > 1) | |||
{ | |||
backlight_config.level--; | |||
eeconfig_write_backlight(backlight_config.raw); | |||
} | |||
dprintf("backlight custom decrease: %u\n", backlight_config.level); | |||
backlight_set(backlight_config.level); | |||
} | |||
#else | |||
if(backlight_config.level > 0) | |||
{ | |||
backlight_config.level--; | |||
@@ -53,11 +75,18 @@ void backlight_decrease(void) | |||
} | |||
dprintf("backlight decrease: %u\n", backlight_config.level); | |||
backlight_set(backlight_config.level); | |||
#endif | |||
} | |||
void backlight_toggle(void) | |||
{ | |||
backlight_config.enable ^= 1; | |||
if (backlight_config.enable) | |||
{ | |||
if (backlight_config.level == 0) { | |||
backlight_config.level = 1; | |||
} | |||
} | |||
eeconfig_write_backlight(backlight_config.raw); | |||
dprintf("backlight toggle: %u\n", backlight_config.enable); | |||
backlight_set(backlight_config.enable ? backlight_config.level : 0); | |||
@@ -75,3 +104,11 @@ void backlight_step(void) | |||
dprintf("backlight step: %u\n", backlight_config.level); | |||
backlight_set(backlight_config.level); | |||
} | |||
void backlight_level(uint8_t level) | |||
{ | |||
backlight_config.level ^= level; | |||
backlight_config.enable = !!backlight_config.level; | |||
eeconfig_write_backlight(backlight_config.raw); | |||
backlight_set(backlight_config.level); | |||
} |
@@ -24,18 +24,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
typedef union { | |||
uint8_t raw; | |||
struct { | |||
bool enable:1; | |||
uint8_t level:7; | |||
bool enable :1; | |||
uint8_t level :7; | |||
}; | |||
} backlight_config_t; | |||
void backlight_init(void); | |||
void backlight_increase(void); | |||
void backlight_decrease(void); | |||
void backlight_toggle(void); | |||
void backlight_step(void); | |||
void backlight_set(uint8_t level); | |||
void backlight_level(uint8_t level); | |||
#endif |
@@ -31,6 +31,7 @@ void bootmagic(void) | |||
/* eeconfig clear */ | |||
if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) { | |||
eeconfig_disable(); | |||
eeconfig_init(); | |||
#ifdef KEYMAP_IN_EEPROM_ENABLE | |||
write_keymap_to_eeprom(); |
@@ -0,0 +1,73 @@ | |||
#include <avr/io.h> | |||
#include <avr/interrupt.h> | |||
#include "led.h" | |||
#include "breathing_led.h" | |||
#include "debug.h" | |||
#define BREATHING_LED_TIMER_TOP F_CPU/256 | |||
static uint8_t breathing_led_duration = 0; | |||
void breathing_led_init(void) | |||
{ | |||
/* Timer3 setup */ | |||
/* CTC mode */ | |||
TCCR3B |= (1<<WGM32); | |||
/* Clock selelct: clk/8 */ | |||
TCCR3B |= (1<<CS30); | |||
/* Set TOP value */ | |||
uint8_t sreg = SREG; | |||
cli(); | |||
OCR3AH = (BREATHING_LED_TIMER_TOP>>8)&0xff; | |||
OCR3AL = BREATHING_LED_TIMER_TOP&0xff; | |||
SREG = sreg; | |||
} | |||
void breathing_led_enable(void) | |||
{ | |||
/* Enable Compare Match Interrupt */ | |||
TIMSK3 |= (1<<OCIE3A); | |||
dprintf("breathing led on: %u\n", TIMSK3 & (1<<OCIE3A)); | |||
} | |||
void breathing_led_disable(void) | |||
{ | |||
/* Disable Compare Match Interrupt */ | |||
TIMSK3 &= ~(1<<OCIE3A); | |||
dprintf("breathing led off: %u\n", TIMSK3 & (1<<OCIE3A)); | |||
} | |||
void breathing_led_toggle(void) | |||
{ | |||
/* Disable Compare Match Interrupt */ | |||
TIMSK3 ^= (1<<OCIE3A); | |||
dprintf("breathing led toggle: %u\n", TIMSK3 & (1<<OCIE3A)); | |||
} | |||
void breathing_led_set_duration(uint8_t dur) | |||
{ | |||
breathing_led_duration = dur; | |||
dprintf("breathing led set duration: %u\n", breathing_led_duration); | |||
} | |||
/* Breathing LED brighness(PWM On period) table | |||
* | |||
* http://www.wolframalpha.com/input/?i=Table%5Bfloor%28%28exp%28sin%28x%2F256*2*pi%2B3%2F2*pi%29%29-1%2Fe%29*%28256%2F%28e-1%2Fe%29%29%29%2C+%7Bx%2C0%2C255%2C1%7D%5D | |||
* Table[floor((exp(sin(x/256*2*pi+3/2*pi))-1/e)*(256/(e-1/e))), {x,0,255,1}] | |||
* (0..255).each {|x| print ((exp(sin(x/256.0*2*PI+3.0/2*PI))-1/E)*(256/(E-1/E))).to_i, ', ' } | |||
*/ | |||
static const uint8_t breathing_table[256] PROGMEM = { | |||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 29, 30, 32, 34, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 56, 58, 61, 63, 66, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98, 102, 105, 108, 112, 116, 119, 123, 126, 130, 134, 138, 142, 145, 149, 153, 157, 161, 165, 169, 173, 176, 180, 184, 188, 192, 195, 199, 203, 206, 210, 213, 216, 219, 223, 226, 228, 231, 234, 236, 239, 241, 243, 245, 247, 248, 250, 251, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 254, 253, 252, 251, 250, 248, 247, 245, 243, 241, 239, 236, 234, 231, 228, 226, 223, 219, 216, 213, 210, 206, 203, 199, 195, 192, 188, 184, 180, 176, 173, 169, 165, 161, 157, 153, 149, 145, 142, 138, 134, 130, 126, 123, 119, 116, 112, 108, 105, 102, 98, 95, 92, 89, 86, 83, 80, 77, 74, 71, 68, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 34, 32, 30, 29, 27, 26, 25, 23, 22, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 11, 10, 9, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |||
}; | |||
ISR(TIMER3_COMPA_vect) | |||
{ | |||
static uint8_t index = 0; | |||
static uint8_t step = 0; | |||
step++; | |||
if (step > breathing_led_duration) { | |||
step = 0; | |||
breathing_led_set_raw(pgm_read_byte(&breathing_table[index])); | |||
index++; | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
#ifndef BREATHING_LED_H | |||
#define BREATHING_LED_H | |||
#ifdef BREATHING_LED_ENABLE | |||
void breathing_led_init(void); | |||
void breathing_led_enable(void); | |||
void breathing_led_disable(void); | |||
void breathing_led_toggle(void); | |||
void breathing_led_set_duration(uint8_t dur); | |||
void breathing_led_set_raw(uint8_t raw); | |||
#else | |||
#define breathing_led_init() | |||
#define breathing_led_enable() | |||
#define breathing_led_disable() | |||
#define breathing_led_toggle() | |||
#define breathing_led_set_duration() | |||
#define breathing_led_set_raw() | |||
#endif | |||
#endif |
@@ -301,13 +301,13 @@ static bool command_common(uint8_t code) | |||
case KC_S: | |||
print("\n\n----- Status -----\n"); | |||
print_val_hex8(host_keyboard_leds()); | |||
print_val_hex8(keyboard_protocol); | |||
print_val_hex8(keyboard_idle); | |||
#ifdef PROTOCOL_PJRC | |||
print_val_hex8(UDCON); | |||
print_val_hex8(UDIEN); | |||
print_val_hex8(UDINT); | |||
print_val_hex8(usb_keyboard_leds); | |||
print_val_hex8(usb_keyboard_protocol); | |||
print_val_hex8(usb_keyboard_idle_config); | |||
print_val_hex8(usb_keyboard_idle_count); | |||
#endif | |||
@@ -2,6 +2,7 @@ | |||
#include <stdbool.h> | |||
#include <avr/eeprom.h> | |||
#include "eeconfig.h" | |||
#include "keymap_ex.h" | |||
void eeconfig_init(void) | |||
{ | |||
@@ -13,6 +14,9 @@ void eeconfig_init(void) | |||
#ifdef BACKLIGHT_ENABLE | |||
eeprom_write_byte(EECONFIG_BACKLIGHT, 0); | |||
#endif | |||
#ifdef KEYMAP_EX_ENABLE | |||
keymap_ex_init(); | |||
#endif | |||
} | |||
void eeconfig_enable(void) | |||
@@ -22,6 +26,9 @@ void eeconfig_enable(void) | |||
void eeconfig_disable(void) | |||
{ | |||
#ifdef KEYMAP_EX_ENABLE | |||
keymap_ex_disable(); | |||
#endif | |||
eeprom_write_word(EECONFIG_MAGIC, 0xFFFF); | |||
} | |||
@@ -24,7 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#ifdef NKRO_ENABLE | |||
bool keyboard_nkro = false; | |||
bool keyboard_nkro = true; | |||
#endif | |||
static host_driver_t *driver; |
@@ -32,6 +32,9 @@ extern "C" { | |||
extern bool keyboard_nkro; | |||
#endif | |||
uint8_t keyboard_idle; | |||
uint8_t keyboard_protocol; | |||
/* host driver */ | |||
void host_set_driver(host_driver_t *driver); |
@@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "bootmagic.h" | |||
#include "eeconfig.h" | |||
#include "backlight.h" | |||
#include "breathing_led.h" | |||
#include "keymap_in_eeprom.h" | |||
#ifdef MOUSEKEY_ENABLE | |||
# include "mousekey.h" | |||
@@ -62,8 +63,15 @@ void keyboard_init(void) | |||
{ | |||
timer_init(); | |||
matrix_init(); | |||
#ifdef LED_MATRIX_ENABLE | |||
led_matrix_init(); | |||
#endif | |||
#ifdef PS2_MOUSE_ENABLE | |||
ps2_mouse_init(); | |||
if (ps2_enabled()) { | |||
ps2_mouse_init(); | |||
} | |||
#endif | |||
#ifdef BOOTMAGIC_ENABLE | |||
@@ -74,6 +82,10 @@ void keyboard_init(void) | |||
backlight_init(); | |||
#endif | |||
#ifdef BREATHING_LED_ENABLE | |||
breathing_led_init(); | |||
#endif | |||
#ifdef KEYMAP_IN_EEPROM_ENABLE | |||
keymap_in_eeprom_init(); | |||
#endif | |||
@@ -128,7 +140,9 @@ MATRIX_LOOP_END: | |||
#endif | |||
#ifdef PS2_MOUSE_ENABLE | |||
ps2_mouse_task(); | |||
if (ps2_enabled()) { | |||
ps2_mouse_task(); | |||
} | |||
#endif | |||
// update LED |
@@ -0,0 +1,91 @@ | |||
/* | |||
Copyright 2013,2014 Kai Ryu <[email protected]> | |||
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 <util/delay.h> | |||
#include "led_matrix.h" | |||
#define LED_MATRIX_TIMER_TOP F_CPU/(256*64)/LED_MATRIX_ROWS | |||
static led_matrix_element_t led_matrix[LED_MATRIX_ROWS][LED_MATRIX_COLS]; | |||
void led_matrix_init(void) | |||
{ | |||
led_matrix_unselect_rows(); | |||
led_matrix_write_cols(0); | |||
/* Timer1 setup */ | |||
/* CTC mode */ | |||
TCCR1B |= (1<<WGM12); | |||
/* Clock selelct: clk/1 */ | |||
TCCR1B |= (1<<CS10); | |||
/* Set TOP value */ | |||
uint8_t sreg = SREG; | |||
cli(); | |||
OCR1AH = (LED_MATRIX_TIMER_TOP >> 8) & 0xFF; | |||
OCR1AL = LED_MATRIX_TIMER_TOP & 0xFF; | |||
SREG = sreg; | |||
} | |||
void led_matrix_enable(void) | |||
{ | |||
/* Enable Compare Match Interrupt */ | |||
TIMSK1 |= _BV(OCIE1A); | |||
} | |||
void led_matrix_disable(void) | |||
{ | |||
/* Disable Compare Match Interrupt */ | |||
TIMSK1 &= ~_BV(OCIE1A); | |||
} | |||
inline | |||
led_matrix_row_t led_matrix_make_cols(uint8_t row, uint8_t pwm) | |||
{ | |||
led_matrix_row_t cols = 0; | |||
for (uint8_t i = 0; i < LED_MATRIX_COLS; i++) { | |||
cols |= ((led_matrix[row][i].value < pwm ? 1 : 0) << i); | |||
} | |||
return cols; | |||
} | |||
inline | |||
void led_matrix_set_value(uint8_t row, uint8_t col, uint8_t value) | |||
{ | |||
led_matrix[row][col].value = value; | |||
} | |||
inline | |||
void led_matrix_set_delta(uint8_t row, uint8_t col, int8_t delta) | |||
{ | |||
led_matrix[row][col].delta = delta; | |||
} | |||
ISR(TIMER1_COMPA_vect) | |||
{ | |||
static uint8_t row = 0; | |||
static uint8_t pwm = 0; | |||
row = (row + 1) % LED_MATRIX_ROWS; | |||
pwm++; | |||
led_matrix_select_row(row); | |||
_delay_us(10); | |||
led_matrix_write_cols(led_matrix_make_cols(row, pwm)); | |||
_delay_us(10); | |||
led_matrix_unselect_rows(); | |||
} |
@@ -0,0 +1,65 @@ | |||
/* | |||
Copyright 2013,2014 Kai Ryu <[email protected]> | |||
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 LED_MATRIX_H | |||
#define LED_MATRIX_H | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
#if (LED_MATRIX_COLS <= 8) | |||
typedef uint8_t led_matrix_row_t; | |||
#elif (LED_MATRIX_COLS <= 16) | |||
typedef uint16_t led_matrix_row_t; | |||
#elif (LED_MATRIX_COLS <= 32) | |||
typedef uint32_t led_matrix_row_t; | |||
#else | |||
#error "LED_MATRIX_COLS: invalid value" | |||
#endif | |||
typedef struct { | |||
union { | |||
int8_t delta; | |||
struct { | |||
bool direction:1; | |||
}; | |||
}; | |||
uint8_t value; | |||
} led_matrix_element_t; | |||
#ifdef LED_MATRIX_ENABLE | |||
void led_matrix_init(void); | |||
void led_matrix_enable(void); | |||
void led_matrix_disable(void); | |||
void led_matrix_init_cols(void); | |||
led_matrix_row_t led_matrix_make_cols(uint8_t row, uint8_t pwm); | |||
void led_matrix_set_value(uint8_t row, uint8_t col, uint8_t value); | |||
void led_matrix_set_delta(uint8_t row, uint8_t col, int8_t delta); | |||
extern void led_matrix_write_cols(led_matrix_row_t cols); | |||
extern void led_matrix_unselect_rows(void); | |||
extern void led_matrix_select_row(uint8_t row); | |||
#else | |||
#define led_matrix_init() | |||
#define led_matrix_enable() | |||
#define led_matrix_disable() | |||
#define led_matrix_init_cols() | |||
#define led_matrix_write_cols() | |||
#define led_matrix_unselect_rows() | |||
#define led_matrix_select_row() | |||
#endif | |||
#endif |
@@ -20,7 +20,7 @@ Wiring: You can change this with editing config.h. | |||
Pin mini DIN MCU | |||
---------------------------------- | |||
1 ~RST PD1 | |||
1 ~RST(TXD) PD3 | |||
2 GND GND | |||
3 ~RDY PD4 | |||
4 RXD PD2 | |||
@@ -37,9 +37,6 @@ Protocol | |||
Signal: Asynchronous, Positive logic, 19200baud, Least bit first | |||
Frame format: 1-Start bit(Lo), 8-Data bits, Odd-Parity, 1-Stop bit | |||
This converter uses software method for testing purpose. AVR UART engine will work better. | |||
Build Firmware |
@@ -1,3 +1,6 @@ | |||
# | |||
# Makefile for Teensy | |||
# | |||
# Target file name (without extension). | |||
TARGET = ps2_usb_lufa | |||
@@ -59,7 +62,7 @@ ARCH = AVR8 | |||
F_USB = $(F_CPU) | |||
# Interrupt driven control endpoint task(+60) | |||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
# Boot Section Size in *bytes* | |||
@@ -68,7 +71,7 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
# Atmel DFU loader 4096 | |||
# LUFA bootloader 4096 | |||
# USBaspLoader 2048 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=512 | |||
# Build Options |
@@ -1,75 +0,0 @@ | |||
# Target file name (without extension). | |||
TARGET = ps2_usb_jis | |||
# Directory common source filess exist | |||
TOP_DIR = ../.. | |||
# Directory keyboard dependent files exist | |||
TARGET_DIR = . | |||
# MCU name, you MUST set this to match the board you are using | |||
# type "make clean" after changing this, so all files will be rebuilt | |||
#MCU = at90usb162 # Teensy 1.0 | |||
MCU = atmega32u4 # Teensy 2.0 | |||
#MCU = at90usb646 # Teensy++ 1.0 | |||
#MCU = at90usb1286 # Teensy++ 2.0 | |||
# Processor frequency. | |||
# Normally the first thing your program should do is set the clock prescaler, | |||
# so your program will run at the correct speed. You should also set this | |||
# variable to same clock speed. The _delay_ms() macro uses this, and many | |||
# examples use this variable to calculate timings. Do not add a "UL" here. | |||
F_CPU = 16000000 | |||
# Build Options | |||
# *Comment out* to disable the options. | |||
# | |||
MOUSEKEY_ENABLE = yes # Mouse keys | |||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||
NKRO_ENABLE = yes # USB Nkey Rollover | |||
#PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened) | |||
#PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin | |||
PS2_USE_BUSYWAIT = yes # uses primitive reference code | |||
# keyboard dependent files | |||
SRC = keymap_jis.c \ | |||
matrix.c \ | |||
led.c | |||
ifdef PS2_USE_USART | |||
SRC += protocol/ps2_usart.c | |||
OPT_DEFS += -DPS2_USE_USART | |||
endif | |||
ifdef PS2_USE_INT | |||
SRC += protocol/ps2.c | |||
OPT_DEFS += -DPS2_USE_INT | |||
endif | |||
ifdef PS2_USE_BUSYWAIT | |||
SRC += protocol/ps2.c | |||
OPT_DEFS += -DPS2_USE_BUSYWAIT | |||
endif | |||
#CONFIG_H = config_pjrc_usart.h | |||
CONFIG_H = config.h | |||
#---------------- Programming Options -------------------------- | |||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/pjrc.mk | |||
include $(TOP_DIR)/protocol.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk |
@@ -0,0 +1,98 @@ | |||
# | |||
# Makefile for TMK keyboard converter rev2 | |||
# https://github.com/tmk/keyboard_converter#pcb-rev1 | |||
# | |||
# Target file name (without extension). | |||
TARGET = ps2_usb_tmk_rev1 | |||
# Directory common source filess exist | |||
TOP_DIR = ../.. | |||
# Directory keyboard dependent files exist | |||
TARGET_DIR = . | |||
# project specific files | |||
SRC = keymap_common.c \ | |||
matrix.c \ | |||
led.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_plain.c $(SRC) | |||
endif | |||
CONFIG_H = config_tmk_rev1.h | |||
# MCU name | |||
MCU = atmega32u4 | |||
# Processor frequency. | |||
# This will define a symbol, F_CPU, in all source code files equal to the | |||
# processor frequency in Hz. You can then use this symbol in your source code to | |||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done | |||
# automatically to create a 32-bit value in your source code. | |||
# | |||
# This will be an integer division of F_USB below, as it is sourced by | |||
# F_USB after it has run through any CPU prescalers. Note that this value | |||
# does not *change* the processor frequency - it should merely be updated to | |||
# reflect the processor speed set externally so that the code can use accurate | |||
# software delays. | |||
F_CPU = 16000000 | |||
# | |||
# LUFA specific | |||
# | |||
# Target architecture (see library "Board Types" documentation). | |||
ARCH = AVR8 | |||
# Input clock frequency. | |||
# This will define a symbol, F_USB, in all source code files equal to the | |||
# input clock frequency (before any prescaling is performed) in Hz. This value may | |||
# differ from F_CPU if prescaling is used on the latter, and is required as the | |||
# raw input clock is fed directly to the PLL sections of the AVR for high speed | |||
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' | |||
# at the end, this will be done automatically to create a 32-bit value in your | |||
# source code. | |||
# | |||
# If no clock division is performed on the input clock inside the AVR (via the | |||
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. | |||
F_USB = $(F_CPU) | |||
# Boot Section Size in *bytes* | |||
# Teensy halfKay 512 | |||
# Teensy++ halfKay 1024 | |||
# Atmel DFU loader 4096 | |||
# LUFA bootloader 4096 | |||
# USBaspLoader 2048 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
# Build Options | |||
# comment out to disable the options. | |||
# | |||
#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
MOUSEKEY_ENABLE = yes # Mouse keys(+4700) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450) | |||
CONSOLE_ENABLE = yes # Console for debug(+400) | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA | |||
# PS/2 Options | |||
# | |||
PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened) | |||
#PS2_USE_BUSYWAIT = yes # uses primitive reference code | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol.mk | |||
include $(TOP_DIR)/protocol/lufa.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk |
@@ -0,0 +1,98 @@ | |||
# | |||
# Makefile for TMK keyboard converter rev2 | |||
# https://github.com/tmk/keyboard_converter#pcb-rev2 | |||
# | |||
# Target file name (without extension). | |||
TARGET = ps2_usb_tmk_rev2 | |||
# Directory common source filess exist | |||
TOP_DIR = ../.. | |||
# Directory keyboard dependent files exist | |||
TARGET_DIR = . | |||
# project specific files | |||
SRC = keymap_common.c \ | |||
matrix.c \ | |||
led.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_plain.c $(SRC) | |||
endif | |||
CONFIG_H = config_tmk_rev2.h | |||
# MCU name | |||
MCU = atmega32u2 | |||
# Processor frequency. | |||
# This will define a symbol, F_CPU, in all source code files equal to the | |||
# processor frequency in Hz. You can then use this symbol in your source code to | |||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done | |||
# automatically to create a 32-bit value in your source code. | |||
# | |||
# This will be an integer division of F_USB below, as it is sourced by | |||
# F_USB after it has run through any CPU prescalers. Note that this value | |||
# does not *change* the processor frequency - it should merely be updated to | |||
# reflect the processor speed set externally so that the code can use accurate | |||
# software delays. | |||
F_CPU = 16000000 | |||
# | |||
# LUFA specific | |||
# | |||
# Target architecture (see library "Board Types" documentation). | |||
ARCH = AVR8 | |||
# Input clock frequency. | |||
# This will define a symbol, F_USB, in all source code files equal to the | |||
# input clock frequency (before any prescaling is performed) in Hz. This value may | |||
# differ from F_CPU if prescaling is used on the latter, and is required as the | |||
# raw input clock is fed directly to the PLL sections of the AVR for high speed | |||
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' | |||
# at the end, this will be done automatically to create a 32-bit value in your | |||
# source code. | |||
# | |||
# If no clock division is performed on the input clock inside the AVR (via the | |||
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. | |||
F_USB = $(F_CPU) | |||
# Boot Section Size in *bytes* | |||
# Teensy halfKay 512 | |||
# Teensy++ halfKay 1024 | |||
# Atmel DFU loader 4096 | |||
# LUFA bootloader 4096 | |||
# USBaspLoader 2048 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
# Build Options | |||
# comment out to disable the options. | |||
# | |||
#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
MOUSEKEY_ENABLE = yes # Mouse keys(+4700) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450) | |||
CONSOLE_ENABLE = yes # Console for debug(+400) | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA | |||
# PS/2 Options | |||
# | |||
PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin | |||
#PS2_USE_BUSYWAIT = yes # uses primitive reference code | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol.mk | |||
include $(TOP_DIR)/protocol/lufa.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk |
@@ -1,31 +1,17 @@ | |||
PS/2 to USB keyboard converter | |||
============================== | |||
This firmware converts PS/2 keyboard protocol to USB and supports only Scan Code Set 2. | |||
PS/2 signal handling implementations | |||
------------------------------------ | |||
Following three methods are used to implement PS/2 signal handling. | |||
### Simple and stupid busy-wait(ps2_busywait.c) | |||
This is expected to implemented with portable C code for reference. | |||
### Interrupt driven(ps2_interrupt.c) | |||
Uses pin interrupt to detect falling edge of clock line. | |||
### USART hardware module(ps2_usart.c) | |||
Uses AVR USART engine to receive PS/2 signal. | |||
To select method edit Makefile. | |||
This firmware converts PS/2 keyboard protocol to USB.(It supports Scan Code Set 2.) | |||
Connect Wires | |||
------------- | |||
In case of Teensy2.0(ATMega32U4): | |||
1. Connect Vcc and GND. | |||
2. Connect Clock and Data line. | |||
- Busywait: Clock is on PD5 and Data on PD2. | |||
- Interrupt: Clock is on PD1 and Data on PD2. | |||
- USART: Clock is on PD5 and Data on PD2. | |||
1. Connect **Vcc** and **GND**. | |||
2. Connect **Clock** and **Data** line. | |||
- **Interrupt**: **Clock** is on `PD1` and **Data** on `PD0`.(Recommended. Soarer's converter compatible) | |||
- **Busywait**: **Clock** is on `PD1` and **Data** on `PD0`. | |||
- **USART**: **Clock** is on `PD5` and **Data** on `PD2`. | |||
3. Optionally you need pull-up register. 1K-10K Ohm is OK. | |||
To change pin configuration edit config.h. | |||
@@ -33,18 +19,41 @@ To change pin configuration edit config.h. | |||
Build Firmware | |||
-------------- | |||
Just run `make`: | |||
For **PJRC Teensy** just run `make`: | |||
$ make clean | |||
$ make | |||
To select keymap: | |||
$ make clean | |||
$ make KEYMAP=[plain|jis|spacefn|...] | |||
After that you will find HEX file `ps2_usb_lufa.hex` in current directory. | |||
- For **TMK converter Rev.1** use `make -f Makefile.tmk_rev1` instead of `make` and HEX file is `ps2_usb_tmk_rev1.hex`. | |||
- For **TMK converter Rev.2** use `make -f Makefile.tmk_rev2` instead of `make` and HEX file is `ps2_usb_tmk_rev2.hex`. | |||
Keymap | |||
------ | |||
Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `keymap_<name>.c` and see keymap document(you can find in top README.md) and existent keymap files. | |||
Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `keymap_<name>.c` and see keymap document(you can find in README.md of top directory) and existent keymap files. | |||
PS/2 signal handling implementations | |||
------------------------------------ | |||
Following three methods can be used to implement PS/2 signal handling. | |||
### Simple and stupid busy-wait(ps2_busywait.c) | |||
This is expected to implemented with portable C code for reference. | |||
### Interrupt driven(ps2_interrupt.c) | |||
Uses pin interrupt to detect falling edge of clock line. | |||
### USART hardware module(ps2_usart.c) | |||
Uses AVR USART engine to receive PS/2 signal. | |||
To select method edit Makefile. | |||
V-USB Support |
@@ -0,0 +1,147 @@ | |||
/* | |||
Copyright 2012 Jun Wako <[email protected]> | |||
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_H | |||
#define CONFIG_H | |||
#include <avr/interrupt.h> | |||
#define VENDOR_ID 0xFEED | |||
#define PRODUCT_ID 0x6512 | |||
#define DEVICE_VER 0x0001 | |||
#define MANUFACTURER t.m.k. | |||
#define PRODUCT PS/2 keyboard converter | |||
#define DESCRIPTION convert PS/2 keyboard to USB | |||
/* matrix size */ | |||
#define MATRIX_ROWS 32 // keycode bit: 3-0 | |||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||
/* key combination for command */ | |||
#define IS_COMMAND() ( \ | |||
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) || \ | |||
keyboard_report->mods == (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RSHIFT)) \ | |||
) | |||
//#define NO_SUSPEND_POWER_DOWN | |||
/* | |||
* PS/2 Busywait | |||
*/ | |||
#ifdef PS2_USE_BUSYWAIT | |||
#define PS2_CLOCK_PORT PORTD | |||
#define PS2_CLOCK_PIN PIND | |||
#define PS2_CLOCK_DDR DDRD | |||
#define PS2_CLOCK_BIT 5 | |||
#define PS2_DATA_PORT PORTD | |||
#define PS2_DATA_PIN PIND | |||
#define PS2_DATA_DDR DDRD | |||
#define PS2_DATA_BIT 2 | |||
#endif | |||
/* | |||
* PS/2 USART | |||
*/ | |||
#ifdef PS2_USE_USART | |||
#if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) | |||
/* XCK for clock line and RXD for data line */ | |||
#define PS2_CLOCK_PORT PORTD | |||
#define PS2_CLOCK_PIN PIND | |||
#define PS2_CLOCK_DDR DDRD | |||
#define PS2_CLOCK_BIT 5 | |||
#define PS2_DATA_PORT PORTD | |||
#define PS2_DATA_PIN PIND | |||
#define PS2_DATA_DDR DDRD | |||
#define PS2_DATA_BIT 2 | |||
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ | |||
/* set DDR of CLOCK as input to be slave */ | |||
#define PS2_USART_INIT() do { \ | |||
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \ | |||
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \ | |||
UCSR1C = ((1 << UMSEL10) | \ | |||
(3 << UPM10) | \ | |||
(0 << USBS1) | \ | |||
(3 << UCSZ10) | \ | |||
(0 << UCPOL1)); \ | |||
UCSR1A = 0; \ | |||
UBRR1H = 0; \ | |||
UBRR1L = 0; \ | |||
} while (0) | |||
#define PS2_USART_RX_INT_ON() do { \ | |||
UCSR1B = ((1 << RXCIE1) | \ | |||
(1 << RXEN1)); \ | |||
} while (0) | |||
#define PS2_USART_RX_POLL_ON() do { \ | |||
UCSR1B = (1 << RXEN1); \ | |||
} while (0) | |||
#define PS2_USART_OFF() do { \ | |||
UCSR1C = 0; \ | |||
UCSR1B &= ~((1 << RXEN1) | \ | |||
(1 << TXEN1)); \ | |||
} while (0) | |||
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1)) | |||
#define PS2_USART_RX_DATA UDR1 | |||
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) | |||
#define PS2_USART_RX_VECT USART1_RX_vect | |||
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) | |||
/* XCK for clock line and RXD for data line */ | |||
#define PS2_CLOCK_PORT PORTD | |||
#define PS2_CLOCK_PIN PIND | |||
#define PS2_CLOCK_DDR DDRD | |||
#define PS2_CLOCK_BIT 4 | |||
#define PS2_DATA_PORT PORTD | |||
#define PS2_DATA_PIN PIND | |||
#define PS2_DATA_DDR DDRD | |||
#define PS2_DATA_BIT 0 | |||
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ | |||
/* set DDR of CLOCK as input to be slave */ | |||
#define PS2_USART_INIT() do { \ | |||
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \ | |||
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \ | |||
UCSR0C = ((1 << UMSEL00) | \ | |||
(3 << UPM00) | \ | |||
(0 << USBS0) | \ | |||
(3 << UCSZ00) | \ | |||
(0 << UCPOL0)); \ | |||
UCSR0A = 0; \ | |||
UBRR0H = 0; \ | |||
UBRR0L = 0; \ | |||
} while (0) | |||
#define PS2_USART_RX_INT_ON() do { \ | |||
UCSR0B = ((1 << RXCIE0) | \ | |||
(1 << RXEN0)); \ | |||
} while (0) | |||
#define PS2_USART_RX_POLL_ON() do { \ | |||
UCSR0B = (1 << RXEN0); \ | |||
} while (0) | |||
#define PS2_USART_OFF() do { \ | |||
UCSR0C = 0; \ | |||
UCSR0B &= ~((1 << RXEN0) | \ | |||
(1 << TXEN0)); \ | |||
} while (0) | |||
#define PS2_USART_RX_READY (UCSR0A & (1<<RXC0)) | |||
#define PS2_USART_RX_DATA UDR0 | |||
#define PS2_USART_ERROR (UCSR0A & ((1<<FE0) | (1<<DOR0) | (1<<UPE0))) | |||
#define PS2_USART_RX_VECT USART_RX_vect | |||
#endif | |||
#endif | |||
#endif |
@@ -0,0 +1,86 @@ | |||
/* | |||
Copyright 2012 Jun Wako <[email protected]> | |||
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_H | |||
#define CONFIG_H | |||
#include <avr/interrupt.h> | |||
#define VENDOR_ID 0xFEED | |||
#define PRODUCT_ID 0x6512 | |||
#define DEVICE_VER 0x0001 | |||
#define MANUFACTURER t.m.k. | |||
#define PRODUCT PS/2 keyboard converter | |||
#define DESCRIPTION convert PS/2 keyboard to USB | |||
/* matrix size */ | |||
#define MATRIX_ROWS 32 // keycode bit: 3-0 | |||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||
/* key combination for command */ | |||
#define IS_COMMAND() ( \ | |||
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) || \ | |||
keyboard_report->mods == (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RSHIFT)) \ | |||
) | |||
//#define NO_SUSPEND_POWER_DOWN | |||
/* | |||
* PS/2 Busywait | |||
*/ | |||
#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 | |||
/* | |||
* PS/2 Pin interrupt | |||
*/ | |||
#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 | |||
#endif |
@@ -20,9 +20,10 @@ CONFIG_H = config.h | |||
# MCU name, you MUST set this to match the board you are using | |||
# type "make clean" after changing this, so all files will be rebuilt | |||
#MCU = at90usb162 # Teensy 1.0 | |||
MCU = atmega32u4 # Teensy 2.0 | |||
#MCU = atmega32u4 # Teensy 2.0 | |||
#MCU = at90usb646 # Teensy++ 1.0 | |||
#MCU = at90usb1286 # Teensy++ 2.0 | |||
MCU = atmega32u2 | |||
# Processor frequency. |
@@ -63,6 +63,8 @@ uint8_t matrix_cols(void) | |||
void matrix_init(void) | |||
{ | |||
DDRD |= (1<<6); | |||
PORTD |= (1<<6); | |||
debug_enable = true; | |||
serial_init(); |
@@ -269,7 +269,7 @@ Default Layer is a layer which always is valid and referred to when actions is n | |||
This sets Default Layer to given parameter `layer` and activate it. | |||
ACTION_DEFAULT_LAYER(layer) | |||
ACTION_DEFAULT_LAYER_SET(layer) | |||
#### 2.2.2 Momentary | |||
@@ -444,6 +444,10 @@ Step through backlight levels. | |||
ACTION_BACKLIGHT_STEP() | |||
Turn a specific backlight level on or off. | |||
ACTION_BACKLIGHT_LEVEL(1) | |||
#### 2.5.2 Turn on / off backlight | |||
Turn the backlight on and off without changing level. | |||
@@ -50,7 +50,9 @@ TARGET_DIR = . | |||
# project specific files | |||
SRC = keymap_common.c \ | |||
matrix.c \ | |||
led.c | |||
led.c \ | |||
backlight.c \ | |||
led_matrix.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
@@ -58,6 +60,7 @@ else | |||
SRC := keymap_poker.c $(SRC) | |||
endif | |||
CONFIG_H = config.h | |||
@@ -110,6 +113,15 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
# USBaspLoader 2048 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
# PCB Revision | |||
ifdef REV | |||
OPT_DEFS += -DGH60_REV_$(REV) | |||
endif | |||
# Additional definitions from command line | |||
ifdef DEFS | |||
OPT_DEFS += $(foreach DEF,$(DEFS),-D$(DEF)) | |||
endif | |||
# Build Options | |||
# comment out to disable the options. | |||
@@ -120,8 +132,13 @@ EXTRAKEY_ENABLE = yes # Audio control and System control(+450) | |||
CONSOLE_ENABLE = yes # Console for debug(+400) | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||
NKRO_ENABLE = yes # USB Nkey Rollover | |||
NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA | |||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||
#PS2_USE_BUSYWAIT = yes | |||
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality | |||
KEYMAP_IN_EEPROM_ENABLE = yes # Read keymap from eeprom | |||
KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor | |||
BREATHING_LED_ENABLE = yes # Enable breathing backlight | |||
# Optimize size but this may cause error "relocation truncated to fit" | |||
@@ -132,5 +149,6 @@ VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/lufa.mk | |||
include $(TOP_DIR)/protocol.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk |
@@ -50,7 +50,8 @@ TARGET_DIR = . | |||
# project specific files | |||
SRC = keymap_common.c \ | |||
matrix.c \ | |||
led.c | |||
led.c \ | |||
backlight.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
@@ -81,18 +82,29 @@ F_CPU = 16000000 | |||
# LUFA bootloader 4096 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
# PCB Revision | |||
ifdef REV | |||
OPT_DEFS += -DGH60_REV_$(REV) | |||
endif | |||
# Additional definitions from command line | |||
ifdef DEFS | |||
OPT_DEFS += $(foreach DEF,$(DEFS),-D$(DEF)) | |||
endif | |||
# Build Options | |||
# comment out to disable the options. | |||
# | |||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
MOUSEKEY_ENABLE = yes # Mouse keys(+5000) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+600) | |||
CONSOLE_ENABLE = yes # Console for debug | |||
MOUSEKEY_ENABLE = yes # Mouse keys(+4700) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450) | |||
CONSOLE_ENABLE = yes # Console for debug(+400) | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||
NKRO_ENABLE = yes # USB Nkey Rollover(+500) | |||
NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA | |||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality | |||
KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor | |||
KEYMAP_IN_EEPROM_ENABLE = yes # Read keymap from eeprom | |||
@@ -103,15 +115,3 @@ VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/pjrc.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk | |||
plain: OPT_DEFS += -DKEYMAP_PLAIN | |||
plain: all | |||
poker: OPT_DEFS += -DKEYMAP_POKER | |||
poker: all | |||
poker_set: OPT_DEFS += -DKEYMAP_POKER_SET | |||
poker_set: all | |||
poker_bit: OPT_DEFS += -DKEYMAP_POKER_BIT | |||
poker_bit: all |
@@ -0,0 +1,159 @@ | |||
/* | |||
Copyright 2013,2014 Kai Ryu <[email protected]> | |||
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> | |||
#include "backlight.h" | |||
#include "breathing_led.h" | |||
#ifdef BACKLIGHT_ENABLE | |||
void backlight_enable(void); | |||
void backlight_disable(void); | |||
inline void backlight_set_raw(uint8_t raw); | |||
#ifdef GH60_REV_CHN | |||
#else | |||
#define SOFTPWM_TIMER_TOP F_CPU/(256*64) | |||
uint8_t softpwm_ocr = 0; | |||
uint8_t softpwm_ocr_buff = 0; | |||
#endif | |||
static const uint8_t backlight_table[] PROGMEM = { | |||
0, 16, 128, 255 | |||
}; | |||
/* Backlight pin configuration | |||
* PWM: PB6 (Rev.CHN) | |||
* GPIO: PF7 PF6 PF5 PF4 (Rev.B) | |||
*/ | |||
void backlight_enable(void) | |||
{ | |||
#if defined(GH60_REV_CHN) | |||
// Turn on PWM | |||
DDRB |= (1<<PB6); | |||
cli(); | |||
TCCR1A |= ((1<<WGM10) | (1<<COM1B1)); | |||
TCCR1B |= ((1<<CS11) | (1<<CS10)); | |||
sei(); | |||
#else | |||
DDRF |= (1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||
PORTF |= (1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||
cli(); | |||
TCCR1B |= (1<<WGM12); | |||
TCCR1B |= (1<<CS10); | |||
OCR1AH = (SOFTPWM_TIMER_TOP>>8)&0xff; | |||
OCR1AL = SOFTPWM_TIMER_TOP&0xff; | |||
TIMSK1 |= (1<<OCIE1A); | |||
sei(); | |||
#endif | |||
} | |||
void backlight_disable(void) | |||
{ | |||
#if defined(GH60_REV_CHN) | |||
// Turn off PWM | |||
cli(); | |||
DDRB &= ~(1<<PB6); | |||
TCCR1A &= ~( (1<<WGM10) | (1<<COM1B1) ); | |||
TCCR1B &= ~( (1<<CS11) | (1<<CS10) ); | |||
sei(); | |||
OCR1B = 0; | |||
#else | |||
DDRF &= ~(1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||
cli(); | |||
TCCR1B &= ~(1<<WGM12); | |||
TCCR1B &= ~(1<<CS10); | |||
TIMSK1 &= ~(1<<OCIE1A); | |||
sei(); | |||
OCR1A = 0; | |||
#endif | |||
} | |||
void backlight_set(uint8_t level) | |||
{ | |||
#ifdef BREATHING_LED_ENABLE | |||
switch (level) { | |||
case 1: | |||
case 2: | |||
case 3: | |||
backlight_enable(); | |||
breathing_led_disable(); | |||
backlight_set_raw(pgm_read_byte(&backlight_table[level])); | |||
break; | |||
case 4: | |||
case 5: | |||
case 6: | |||
backlight_enable(); | |||
breathing_led_enable(); | |||
breathing_led_set_duration(6 - level); | |||
break; | |||
case 0: | |||
default: | |||
breathing_led_disable(); | |||
backlight_disable(); | |||
break; | |||
} | |||
#else | |||
if (level > 0) { | |||
backlight_enable(); | |||
backlight_set_raw(pgm_read_byte(&backlight_table[level])); | |||
} | |||
else { | |||
backlight_disable(); | |||
} | |||
#endif | |||
} | |||
#ifdef BREATHING_LED_ENABLE | |||
void breathing_led_set_raw(uint8_t raw) | |||
{ | |||
backlight_set_raw(raw); | |||
} | |||
#endif | |||
inline void backlight_set_raw(uint8_t raw) | |||
{ | |||
#if defined(GH60_REV_CHN) | |||
OCR1B = raw; | |||
#else | |||
softpwm_ocr_buff = raw; | |||
#endif | |||
} | |||
#if defined(GH60_REV_CHN) | |||
#else | |||
ISR(TIMER1_COMPA_vect) | |||
{ | |||
static uint8_t pwm = 0; | |||
pwm++; | |||
// LED on | |||
if (pwm == 0) { | |||
//PORTB |= (1<<PB6); | |||
PORTF &= ~(1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||
softpwm_ocr = softpwm_ocr_buff; | |||
} | |||
// LED off | |||
if (pwm == softpwm_ocr) { | |||
//PORTB &= ~(1<<PB6); | |||
PORTF |= (1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||
} | |||
} | |||
#endif | |||
#endif |
@@ -41,8 +41,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
/* Set 0 if debouncing isn't needed */ | |||
#define DEBOUNCE 5 | |||
/* number of backlight levels */ | |||
#ifdef BREATHING_LED_ENABLE | |||
#define BACKLIGHT_LEVELS 6 | |||
#else | |||
#define BACKLIGHT_LEVELS 3 | |||
#endif | |||
#ifdef GH60_REV_CNY | |||
#define LED_MATRIX_ROWS 6 | |||
#define LED_MATRIX_COLS 14 | |||
#endif | |||
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ | |||
#define LOCKING_SUPPORT_ENABLE | |||
/* Locking resynchronize hack */ | |||
#define LOCKING_RESYNC_ENABLE | |||
@@ -51,7 +64,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ | |||
) | |||
/* PS2 mouse support */ | |||
#ifdef PS2_MOUSE_ENABLE | |||
#define PS2_CLOCK_PORT PORTF | |||
#define PS2_CLOCK_PIN PINF | |||
#define PS2_CLOCK_DDR DDRF | |||
#define PS2_CLOCK_BIT PF7 | |||
#define PS2_DATA_PORT PORTF | |||
#define PS2_DATA_PIN PINF | |||
#define PS2_DATA_DDR DDRF | |||
#define PS2_DATA_BIT PF6 | |||
#endif | |||
/* | |||
* Feature disable options |
@@ -43,13 +43,13 @@ extern const uint16_t fn_actions[]; | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, \ | |||
K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \ | |||
K40, K41, K42, K45, K49, K4A, K4B, K4C, K4D \ | |||
K40, K41, K42, K45, K4A, K4B, K4C, K4D \ | |||
) { \ | |||
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D }, \ | |||
{ KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D }, \ | |||
{ KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D }, \ | |||
{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D }, \ | |||
{ KC_##K40, KC_##K41, KC_##K42, KC_NO, KC_NO, KC_##K45, KC_NO, KC_NO, KC_NO, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D } \ | |||
{ KC_##K40, KC_##K41, KC_##K42, KC_NO, KC_NO, KC_##K45, KC_NO, KC_NO, KC_NO, KC_NO, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D } \ | |||
} | |||
/* ANSI valiant. No extra keys for ISO */ | |||
@@ -64,22 +64,7 @@ extern const uint16_t fn_actions[]; | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO, K2D, \ | |||
K30, NO, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, NO, K3D, \ | |||
K40, K41, K42, K45, NO, K4A, K4B, K4C, K4D \ | |||
) | |||
#define KEYMAP_HHKB( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K49,\ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2D, \ | |||
K30, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3D, K3C, \ | |||
K40, K41, K42, K45, K4A, K4B, K4C, K4D \ | |||
) KEYMAP( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO, K2D, \ | |||
K30, NO, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \ | |||
K40, K41, K42, K45, K49, K4A, K4B, K4C, K4D \ | |||
) | |||
#endif |
@@ -0,0 +1,72 @@ | |||
#include "keymap_common.h" | |||
// Poker2 | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint8_t keymaps[KEYMAPS_COUNT][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | |||
#else | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
#endif | |||
/* Keymap 0: Default Layer | |||
* ,-----------------------------------------------------------. | |||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | |||
* |-----------------------------------------------------------| | |||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |||
* |-----------------------------------------------------------| | |||
* |Caps | A| S| D| F| G| H| J| K| L| ;| '|Return | | |||
* |-----------------------------------------------------------| | |||
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0| | |||
* |-----------------------------------------------------------| | |||
* |Ctrl|Gui |Alt | Space |Alt |Fn0 |Gui |Ctrl| | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP( | |||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \ | |||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,NO, ENT, \ | |||
LSFT,NO, Z, X, C, V, B, N, M, COMM,DOT, SLSH,FN0, RSFT, \ | |||
LCTL,LGUI,LALT, SPC, NO, RALT,FN0, RGUI,RCTL), | |||
/* Keymap 1: Fn Layer | |||
* ,-----------------------------------------------------------. | |||
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | |||
* |-----------------------------------------------------------| | |||
* | | |Up | | | |Cal| |Ins| |Psc|Slk|Pau| | | |||
* |-----------------------------------------------------------| | |||
* | |Lef|Dow|Rig| | | | | | |Hom|PgU| | | |||
* |-----------------------------------------------------------| | |||
* | | |App|Fn1|Fn2|Fn3|VoD|VoU|Mut|End|PgD| | | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | | | | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP( | |||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, \ | |||
TRNS,TRNS,UP, TRNS,TRNS,TRNS,CALC,TRNS,INS, TRNS,PSCR,SLCK,PAUS,TRNS, \ | |||
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,NO, TRNS, \ | |||
TRNS,NO, TRNS,APP, FN1, FN2, FN3, VOLD,VOLU,MUTE,END, PGDN,TRNS,TRNS, \ | |||
TRNS,TRNS,TRNS, TRNS, NO, TRNS,TRNS,TRNS,TRNS), | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint16_t fn_actions[FN_ACTIONS_COUNT] __attribute__ ((section (".keymap.fn_actions"))) = { | |||
#else | |||
const uint16_t fn_actions[] PROGMEM = { | |||
#endif | |||
/* Poker2 Layout */ | |||
[0] = ACTION_LAYER_MOMENTARY(1), | |||
[1] = ACTION_BACKLIGHT_DECREASE(), | |||
[2] = ACTION_BACKLIGHT_TOGGLE(), | |||
[3] = ACTION_BACKLIGHT_INCREASE() | |||
}; | |||
#ifdef KEYMAP_EX_ENABLE | |||
uint16_t keys_count(void) { | |||
return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_ROWS * MATRIX_COLS; | |||
} | |||
uint16_t fn_actions_count(void) { | |||
return sizeof(fn_actions) / sizeof(fn_actions[0]); | |||
} | |||
#endif |
@@ -0,0 +1,98 @@ | |||
/* | |||
Copyright 2013,2014 Kai Ryu <[email protected]> | |||
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 "led_matrix.h" | |||
#ifdef LED_MATRIX_ENABLE | |||
#if defined(GH60_REV_CNY) | |||
/* LED Column pin configuration | |||
* pin: F0 F1 E6 C7 C6 B7 D4 B0 B1 B5 B4 D7 D6 B3 (Rev.CNY) | |||
*/ | |||
void led_matrix_write_cols(led_matrix_row_t cols) | |||
{ | |||
(cols & (1<<0)) ? (PORTF |= (1<<PF0)) : (PORTF &= ~(1<<PF0)); | |||
(cols & (1<<1)) ? (PORTF |= (1<<PF1)) : (PORTF &= ~(1<<PF1)); | |||
(cols & (1<<2)) ? (PORTE |= (1<<PE6)) : (PORTE &= ~(1<<PE6)); | |||
(cols & (1<<3)) ? (PORTC |= (1<<PC7)) : (PORTC &= ~(1<<PC7)); | |||
(cols & (1<<4)) ? (PORTC |= (1<<PC6)) : (PORTC &= ~(1<<PC6)); | |||
(cols & (1<<5)) ? (PORTB |= (1<<PB7)) : (PORTB &= ~(1<<PB7)); | |||
(cols & (1<<6)) ? (PORTD |= (1<<PD4)) : (PORTD &= ~(1<<PD4)); | |||
(cols & (1<<7)) ? (PORTB |= (1<<PB0)) : (PORTB &= ~(1<<PB0)); | |||
(cols & (1<<8)) ? (PORTB |= (1<<PB1)) : (PORTB &= ~(1<<PB1)); | |||
(cols & (1<<9)) ? (PORTB |= (1<<PB5)) : (PORTB &= ~(1<<PB5)); | |||
(cols & (1<<10)) ? (PORTB |= (1<<PB4)) : (PORTB &= ~(1<<PB4)); | |||
(cols & (1<<11)) ? (PORTD |= (1<<PD7)) : (PORTD &= ~(1<<PD7)); | |||
(cols & (1<<12)) ? (PORTD |= (1<<PD6)) : (PORTD &= ~(1<<PD6)); | |||
(cols & (1<<13)) ? (PORTB |= (1<<PB3)) : (PORTB &= ~(1<<PB3)); | |||
} | |||
/* LED Row pin configuration | |||
* row: 0 1 2 3 4 5 | |||
* pin: B6 F5 F6 F7 F4 B2 | |||
*/ | |||
void led_matrix_unselect_rows(void) | |||
{ | |||
// unselect key matrix rows | |||
//DDRD &= ~0b00101111; | |||
//PORTD &= ~0b00101111; | |||
// bit 76543210 | |||
DDRB &= ~0b01000100; | |||
PORTB &= ~0b01000100; | |||
// bit 76543210 | |||
DDRF &= ~0b11110000; | |||
PORTF &= ~0b11110000; | |||
} | |||
/* LED Row pin configuration | |||
* row: 0 1 2 3 4 5 | |||
* pin: B6 F5 F6 F7 F4 B2 | |||
*/ | |||
void led_matrix_select_row(uint8_t row) | |||
{ | |||
switch (row) { | |||
case 0: | |||
DDRB |= (1<<PB6); | |||
PORTB |= (1<<PB6); | |||
break; | |||
case 1: | |||
DDRF |= (1<<PF5); | |||
PORTF |= (1<<PF5); | |||
break; | |||
case 2: | |||
DDRF |= (1<<PF6); | |||
PORTF |= (1<<PF6); | |||
break; | |||
case 3: | |||
DDRF |= (1<<PF7); | |||
PORTF |= (1<<PF7); | |||
break; | |||
case 4: | |||
DDRF |= (1<<PF4); | |||
PORTF |= (1<<PF4); | |||
break; | |||
case 5: | |||
DDRB |= (1<<PB2); | |||
PORTB |= (1<<PB2); | |||
break; | |||
} | |||
} | |||
#endif | |||
#endif |
@@ -26,6 +26,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "debug.h" | |||
#include "util.h" | |||
#include "matrix.h" | |||
#ifdef PS2_MOUSE_ENABLE | |||
#include "ps2.h" | |||
#endif | |||
#ifndef DEBOUNCE | |||
@@ -42,6 +45,14 @@ static void init_cols(void); | |||
static void unselect_rows(void); | |||
static void select_row(uint8_t row); | |||
#ifdef PS2_MOUSE_ENABLE | |||
static uint8_t ps2_mouse_detected; | |||
uint8_t ps2_enabled(void) | |||
{ | |||
return ps2_mouse_detected; | |||
} | |||
#endif | |||
inline | |||
uint8_t matrix_rows(void) | |||
@@ -57,6 +68,23 @@ uint8_t matrix_cols(void) | |||
void matrix_init(void) | |||
{ | |||
// disable JTAG | |||
MCUCR = (1<<JTD); | |||
MCUCR = (1<<JTD); | |||
#ifdef PS2_MOUSE_ENABLE | |||
// ps2 mouse detect | |||
DDRF &= ~(1<<PF5 | 1<<PF4); | |||
PORTF |= (1<<PF5 | 1<<PF4); | |||
if (PINF & (1<<PF5 | 1 <<PF4)) { | |||
ps2_mouse_detected = 0; | |||
} | |||
else { | |||
ps2_mouse_detected = 1; | |||
} | |||
DDRF |= (1<<PF5 | 1<<PF4); | |||
#endif | |||
// initialize row and col | |||
unselect_rows(); | |||
init_cols(); | |||
@@ -72,6 +100,9 @@ uint8_t matrix_scan(void) | |||
{ | |||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||
select_row(i); | |||
#ifdef HYBRID_MATRIX | |||
init_cols(); | |||
#endif | |||
_delay_us(30); // without this wait read unstable value. | |||
matrix_row_t cols = read_cols(); | |||
if (matrix_debouncing[i] != cols) { | |||
@@ -135,27 +166,70 @@ uint8_t matrix_key_count(void) | |||
} | |||
/* Column pin configuration | |||
* col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |||
* pin: F0 F1 E6 C7 C6 B6 D4 B1 B0 B5 B4 D7 D6 B3 (Rev.A) | |||
* pin: B7 (Rev.B) | |||
* pin: F1 F0 E6 D7 D6 D4 C7 C6 B6 B5 B4 B3 B1 B0 (Rev.A) | |||
* pin: F1 F0 E6 D7 D6 D4 C7 C6 B7 B6 B5 B4 B3 B1 (Rev.B) | |||
* pin: F1 F0 E6 D7 D6 D4 C7 C6 B7 B5 B4 B3 B1 B0 (Rev.CHN/CNY) | |||
*/ | |||
static void init_cols(void) | |||
{ | |||
// Input with pull-up(DDR:0, PORT:1) | |||
DDRF &= ~(1<<0 | 1<<1); | |||
PORTF |= (1<<0 | 1<<1); | |||
DDRE &= ~(1<<6); | |||
PORTE |= (1<<6); | |||
DDRD &= ~(1<<7 | 1<<6 | 1<<4); | |||
PORTD |= (1<<7 | 1<<6 | 1<<4); | |||
DDRC &= ~(1<<7 | 1<<6); | |||
PORTC |= (1<<7 | 1<<6); | |||
DDRB &= ~(1<<7 | 1<<6 | 1<< 5 | 1<<4 | 1<<3 | 1<<1 | 1<<0); | |||
PORTB |= (1<<7 | 1<<6 | 1<< 5 | 1<<4 | 1<<3 | 1<<1 | 1<<0); | |||
DDRF &= ~(1<<PF1 | 1<<PF0); | |||
PORTF |= (1<<PF1 | 1<<PF0); | |||
DDRE &= ~(1<<PE6); | |||
PORTE |= (1<<PE6); | |||
DDRD &= ~(1<<PD7 | 1<<PD6 | 1<<PD4); | |||
PORTD |= (1<<PD7 | 1<<PD6 | 1<<PD4); | |||
DDRC &= ~(1<<PC7 | 1<<PC6); | |||
PORTC |= (1<<PC7 | 1<<PC6); | |||
#if defined(GH60_REV_CHN) || defined(GH60_REV_CNY) | |||
DDRB &= ~(1<<PB7 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
PORTB |= (1<<PB7 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
#else | |||
DDRB &= ~(1<<PB7 | 1<<PB6 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
PORTB |= (1<<PB7 | 1<<PB6 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
#endif | |||
} | |||
/* Column pin configuration | |||
* col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |||
* pin: F0 F1 E6 C7 C6 B6 D4 B1 B0 B5 B4 D7 D6 B3 (Rev.A) | |||
* pin: F0 F1 E6 C7 C6 B6 D4 B1 B7 B5 B4 D7 D6 B3 (Rev.B) | |||
* pin: F0 F1 E6 C7 C6 B7 D4 B1 B0 B5 B4 D7 D6 B3 (Rev.CHN) | |||
* pin: F0 F1 E6 C7 C6 B7 D4 B0 B1 B5 B4 D7 D6 B3 (Rev.CNY) | |||
*/ | |||
static matrix_row_t read_cols(void) | |||
{ | |||
#if defined(GH60_REV_CHN) | |||
return (PINF&(1<<PF0) ? 0 : (1<<0)) | | |||
(PINF&(1<<PF1) ? 0 : (1<<1)) | | |||
(PINE&(1<<PE6) ? 0 : (1<<2)) | | |||
(PINC&(1<<PC7) ? 0 : (1<<3)) | | |||
(PINC&(1<<PC6) ? 0 : (1<<4)) | | |||
(PINB&(1<<PB7) ? 0 : (1<<5)) | | |||
(PIND&(1<<PD4) ? 0 : (1<<6)) | | |||
(PINB&(1<<PB1) ? 0 : (1<<7)) | | |||
(PINB&(1<<PB0) ? 0 : (1<<8)) | | |||
(PINB&(1<<PB5) ? 0 : (1<<9)) | | |||
(PINB&(1<<PB4) ? 0 : (1<<10)) | | |||
(PIND&(1<<PD7) ? 0 : (1<<11)) | | |||
(PIND&(1<<PD6) ? 0 : (1<<12)) | | |||
(PINB&(1<<PB3) ? 0 : (1<<13)); | |||
#elif defined(GH60_REV_CNY) | |||
return (PINF&(1<<PF0) ? 0 : (1<<0)) | | |||
(PINF&(1<<PF1) ? 0 : (1<<1)) | | |||
(PINE&(1<<PE6) ? 0 : (1<<2)) | | |||
(PINC&(1<<PC7) ? 0 : (1<<3)) | | |||
(PINC&(1<<PC6) ? 0 : (1<<4)) | | |||
(PINB&(1<<PB7) ? 0 : (1<<5)) | | |||
(PIND&(1<<PD4) ? 0 : (1<<6)) | | |||
(PINB&(1<<PB0) ? 0 : (1<<7)) | | |||
(PINB&(1<<PB1) ? 0 : (1<<8)) | | |||
(PINB&(1<<PB5) ? 0 : (1<<9)) | | |||
(PINB&(1<<PB4) ? 0 : (1<<10)) | | |||
(PIND&(1<<PD7) ? 0 : (1<<11)) | | |||
(PIND&(1<<PD6) ? 0 : (1<<12)) | | |||
(PINB&(1<<PB3) ? 0 : (1<<13)); | |||
#else | |||
return (PINF&(1<<0) ? 0 : (1<<0)) | | |||
(PINF&(1<<1) ? 0 : (1<<1)) | | |||
(PINE&(1<<6) ? 0 : (1<<2)) | | |||
@@ -170,6 +244,7 @@ static matrix_row_t read_cols(void) | |||
(PIND&(1<<7) ? 0 : (1<<11)) | | |||
(PIND&(1<<6) ? 0 : (1<<12)) | | |||
(PINB&(1<<3) ? 0 : (1<<13)); | |||
#endif | |||
} | |||
/* Row pin configuration |
@@ -0,0 +1,146 @@ | |||
#---------------------------------------------------------------------------- | |||
# On command line: | |||
# | |||
# make all = Make software. | |||
# | |||
# make clean = Clean out built project files. | |||
# | |||
# make coff = Convert ELF to AVR COFF. | |||
# | |||
# make extcoff = Convert ELF to AVR Extended COFF. | |||
# | |||
# make program = Download the hex file to the device. | |||
# Please customize your programmer settings(PROGRAM_CMD) | |||
# | |||
# make teensy = Download the hex file to the device, using teensy_loader_cli. | |||
# (must have teensy_loader_cli installed). | |||
# | |||
# make dfu = Download the hex file to the device, using dfu-programmer (must | |||
# have dfu-programmer installed). | |||
# | |||
# make flip = Download the hex file to the device, using Atmel FLIP (must | |||
# have Atmel FLIP installed). | |||
# | |||
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer | |||
# (must have dfu-programmer installed). | |||
# | |||
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP | |||
# (must have Atmel FLIP installed). | |||
# | |||
# make debug = Start either simulavr or avarice as specified for debugging, | |||
# with avr-gdb or avr-insight as the front end for debugging. | |||
# | |||
# make filename.s = Just compile filename.c into the assembler code only. | |||
# | |||
# make filename.i = Create a preprocessed source file for use in submitting | |||
# bug reports to the GCC project. | |||
# | |||
# To rebuild project do "make clean" then "make all". | |||
#---------------------------------------------------------------------------- | |||
# Target file name (without extension). | |||
TARGET = ghpad_lufa | |||
# Directory common source filess exist | |||
TOP_DIR = ../.. | |||
# Directory keyboard dependent files exist | |||
TARGET_DIR = . | |||
# project specific files | |||
SRC = keymap_common.c \ | |||
matrix.c \ | |||
led.c \ | |||
backlight.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_4x6.c $(SRC) | |||
endif | |||
CONFIG_H = config.h | |||
# MCU name | |||
#MCU = at90usb1287 | |||
MCU = atmega32u4 | |||
# Processor frequency. | |||
# This will define a symbol, F_CPU, in all source code files equal to the | |||
# processor frequency in Hz. You can then use this symbol in your source code to | |||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done | |||
# automatically to create a 32-bit value in your source code. | |||
# | |||
# This will be an integer division of F_USB below, as it is sourced by | |||
# F_USB after it has run through any CPU prescalers. Note that this value | |||
# does not *change* the processor frequency - it should merely be updated to | |||
# reflect the processor speed set externally so that the code can use accurate | |||
# software delays. | |||
F_CPU = 16000000 | |||
# | |||
# LUFA specific | |||
# | |||
# Target architecture (see library "Board Types" documentation). | |||
ARCH = AVR8 | |||
# Input clock frequency. | |||
# This will define a symbol, F_USB, in all source code files equal to the | |||
# input clock frequency (before any prescaling is performed) in Hz. This value may | |||
# differ from F_CPU if prescaling is used on the latter, and is required as the | |||
# raw input clock is fed directly to the PLL sections of the AVR for high speed | |||
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' | |||
# at the end, this will be done automatically to create a 32-bit value in your | |||
# source code. | |||
# | |||
# If no clock division is performed on the input clock inside the AVR (via the | |||
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. | |||
F_USB = $(F_CPU) | |||
# Interrupt driven control endpoint task(+60) | |||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
# Boot Section Size in *bytes* | |||
# Teensy halfKay 512 | |||
# Teensy++ halfKay 1024 | |||
# Atmel DFU loader 4096 | |||
# LUFA bootloader 4096 | |||
# USBaspLoader 2048 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
# Additional definitions from command line | |||
ifdef DEFS | |||
OPT_DEFS += $(foreach DEF,$(DEFS),-D$(DEF)) | |||
endif | |||
# Build Options | |||
# comment out to disable the options. | |||
# | |||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
MOUSEKEY_ENABLE = yes # Mouse keys(+4700) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450) | |||
CONSOLE_ENABLE = yes # Console for debug(+400) | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||
NKRO_ENABLE = yes # USB Nkey Rollover | |||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality | |||
KEYMAP_EX_ENABLE = yes # External keymap in eeprom | |||
KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor | |||
# Optimize size but this may cause error "relocation truncated to fit" | |||
#EXTRALDFLAGS = -Wl,--relax | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/lufa.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk |
@@ -0,0 +1,101 @@ | |||
#---------------------------------------------------------------------------- | |||
# On command line: | |||
# | |||
# make all = Make software. | |||
# | |||
# make clean = Clean out built project files. | |||
# | |||
# make coff = Convert ELF to AVR COFF. | |||
# | |||
# make extcoff = Convert ELF to AVR Extended COFF. | |||
# | |||
# make program = Download the hex file to the device. | |||
# Please customize your programmer settings(PROGRAM_CMD) | |||
# | |||
# make teensy = Download the hex file to the device, using teensy_loader_cli. | |||
# (must have teensy_loader_cli installed). | |||
# | |||
# make dfu = Download the hex file to the device, using dfu-programmer (must | |||
# have dfu-programmer installed). | |||
# | |||
# make flip = Download the hex file to the device, using Atmel FLIP (must | |||
# have Atmel FLIP installed). | |||
# | |||
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer | |||
# (must have dfu-programmer installed). | |||
# | |||
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP | |||
# (must have Atmel FLIP installed). | |||
# | |||
# make debug = Start either simulavr or avarice as specified for debugging, | |||
# with avr-gdb or avr-insight as the front end for debugging. | |||
# | |||
# make filename.s = Just compile filename.c into the assembler code only. | |||
# | |||
# make filename.i = Create a preprocessed source file for use in submitting | |||
# bug reports to the GCC project. | |||
# | |||
# To rebuild project do "make clean" then "make all". | |||
#---------------------------------------------------------------------------- | |||
# Target file name (without extension). | |||
TARGET = ghpad_pjrc | |||
# Directory common source filess exist | |||
TOP_DIR = ../.. | |||
# Directory keyboard dependent files exist | |||
TARGET_DIR = . | |||
# project specific files | |||
SRC = keymap.c \ | |||
matrix.c \ | |||
led.c | |||
CONFIG_H = config.h | |||
# MCU name, you MUST set this to match the board you are using | |||
# type "make clean" after changing this, so all files will be rebuilt | |||
MCU = atmega32u4 | |||
#MCU = at90usb1286 | |||
# Processor frequency. | |||
# Normally the first thing your program should do is set the clock prescaler, | |||
# so your program will run at the correct speed. You should also set this | |||
# variable to same clock speed. The _delay_ms() macro uses this, and many | |||
# examples use this variable to calculate timings. Do not add a "UL" here. | |||
F_CPU = 16000000 | |||
# Boot Section Size in *bytes* | |||
# Teensy halfKay 512 | |||
# Atmel DFU loader 4096 | |||
# LUFA bootloader 4096 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
# Build Options | |||
# comment out to disable the options. | |||
# | |||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
MOUSEKEY_ENABLE = yes # Mouse keys(+5000) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+600) | |||
CONSOLE_ENABLE = yes # Console for debug | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||
NKRO_ENABLE = yes # USB Nkey Rollover(+500) | |||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/pjrc.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk | |||
plain: OPT_DEFS += -DKEYMAP_PLAIN | |||
plain: all |
@@ -0,0 +1,82 @@ | |||
/* | |||
Copyright 2013,2014 Kai Ryu <[email protected]> | |||
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> | |||
#include "backlight.h" | |||
static const uint8_t backlight_table[] PROGMEM = { | |||
0, 16, 128, 255 | |||
}; | |||
uint8_t softpwm_ocr = 0; | |||
/* Backlight pin configuration | |||
* PWM: PB5 (RevRS) | |||
* GPIO: PF7 PF6 PF5 | |||
*/ | |||
void backlight_set(uint8_t level) | |||
{ | |||
if (level > 0) { | |||
// Turn on PWM | |||
cli(); | |||
// Hard PWM | |||
DDRB |= (1<<PB5); | |||
PORTB |= (1<<PB5); | |||
TCCR1A |= ((1<<WGM10) | (1<<COM1A1)); | |||
TCCR1B |= ((1<<CS11) | (1<<CS10)); | |||
// Soft PWM | |||
DDRF |= ((1<<PF7) | (1<<PF6) | (1<<PF5)); | |||
PORTF |= ((1<<PF7) | (1<<PF6) | (1<<PF5)); | |||
TIMSK1 |= ((1<<OCIE1A) | (1<<TOIE1)); | |||
TIFR1 |= (1<<TOV1); | |||
sei(); | |||
// Set PWM | |||
OCR1A = pgm_read_byte(&backlight_table[level]); | |||
softpwm_ocr = pgm_read_byte(&backlight_table[level]); | |||
} | |||
else { | |||
// Turn off PWM | |||
cli(); | |||
// Hard PWM | |||
DDRB |= (1<<PB5); | |||
PORTB &= ~(1<<PB5); | |||
TCCR1A &= ~((1<<WGM10) | (1<<COM1A1)); | |||
TCCR1B &= ~((1<<CS11) | (1<<CS10)); | |||
// Soft PWM | |||
DDRF |= ((1<<PF7) | (1<<PF6) | (1<<PF5)); | |||
PORTF |= ((1<<PF7) | (1<<PF6) | (1<<PF5)); | |||
TIMSK1 |= ((1<<OCIE1A) | (1<<TOIE1)); | |||
TIFR1 |= (1<<TOV1); | |||
sei(); | |||
// Set PWM | |||
OCR1A = 0; | |||
softpwm_ocr = 0; | |||
} | |||
} | |||
ISR(TIMER1_COMPA_vect) | |||
{ | |||
// LED off | |||
PORTF |= ((1<<PF7) | (1<<PF6) | (1<<PF5)); | |||
} | |||
ISR(TIMER1_OVF_vect) | |||
{ | |||
// LED on | |||
PORTF &= ~((1<<PF7) | (1<<PF6) | (1<<PF5)); | |||
} |
@@ -0,0 +1,85 @@ | |||
/* | |||
Copyright 2012 Jun Wako <[email protected]> | |||
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_H | |||
#define CONFIG_H | |||
/* USB Device descriptor parameter */ | |||
#define VENDOR_ID 0xFEED | |||
#define PRODUCT_ID 0x6060 | |||
#define DEVICE_VER 0x0002 | |||
#define MANUFACTURER geekhack | |||
#define PRODUCT GHPad | |||
#define DESCRIPTION t.m.k. keyboard firmware for GHPad | |||
/* key matrix size */ | |||
#define MATRIX_ROWS 6 | |||
#define MATRIX_COLS 4 | |||
/* keymap in eeprom */ | |||
#define FN_ACTIONS_COUNT 32 | |||
#define KEYMAPS_COUNT 32 | |||
/* define if matrix has ghost */ | |||
//#define MATRIX_HAS_GHOST | |||
/* Set 0 if debouncing isn't needed */ | |||
#define DEBOUNCE 5 | |||
/* number of backlight levels */ | |||
#define BACKLIGHT_LEVELS 3 | |||
/* number of backlight levels */ | |||
//#define BACKLIGHT_LEVELS 3 | |||
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ | |||
#define LOCKING_SUPPORT_ENABLE | |||
/* Locking resynchronize hack */ | |||
#define LOCKING_RESYNC_ENABLE | |||
/* key combination for command */ | |||
#ifndef __ASSEMBLER__ | |||
#include "matrix.h" | |||
#define IS_COMMAND() ( \ | |||
matrix_is_on(0, 0) && matrix_is_on(0, MATRIX_COLS - 1) \ | |||
) | |||
#endif | |||
/* boot magic key */ | |||
#define BOOTMAGIC_KEY_SALT KC_FN0 | |||
/* | |||
* Feature disable options | |||
* These options are also useful to firmware size reduction. | |||
*/ | |||
/* disable debug print */ | |||
//#define NO_DEBUG | |||
/* disable print */ | |||
//#define NO_PRINT | |||
/* disable action features */ | |||
//#define NO_ACTION_LAYER | |||
//#define NO_ACTION_TAPPING | |||
//#define NO_ACTION_ONESHOT | |||
//#define NO_ACTION_MACRO | |||
//#define NO_ACTION_FUNCTION | |||
#endif |
@@ -0,0 +1,51 @@ | |||
#include "keymap_common.h" | |||
// 4x6 Keypad | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint8_t keymaps[KEYMAPS_COUNT][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | |||
#else | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
#endif | |||
/* Keymap 0: Default Layer | |||
* ,---------------. | |||
* |Esc|Tab|= |Bs | | |||
* |---+---+---+---| | |||
* |Num|/ |* |- | | |||
* |---+---+---+---| | |||
* |7 |8 |9 |+ | | |||
* |---+---+---| | | |||
* |4 |5 |6 | | | |||
* |---+---+---+---| | |||
* |1 |2 |3 |Ent| | |||
* |---+---+---| | | |||
* |0 |. | | | |||
* `---------------' | |||
*/ | |||
[0] = KEYMAP( | |||
ESC, TAB, PEQL,BSPC, \ | |||
NLCK,PSLS,PAST,PMNS, \ | |||
P7, P8, P9, PPLS, \ | |||
P4, P5, P6, PENT, \ | |||
P1, P2, P3, PENT, \ | |||
P0, NO, PDOT,NO) | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint16_t fn_actions[FN_ACTIONS_COUNT] __attribute__ ((section (".keymap.fn_actions"))) = { | |||
#else | |||
const uint16_t fn_actions[] PROGMEM = { | |||
#endif | |||
}; | |||
#ifdef KEYMAP_EX_ENABLE | |||
uint16_t keys_count(void) { | |||
return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_ROWS * MATRIX_COLS; | |||
} | |||
uint16_t fn_actions_count(void) { | |||
return sizeof(fn_actions) / sizeof(fn_actions[0]); | |||
} | |||
#endif |
@@ -0,0 +1,54 @@ | |||
#include "keymap_common.h" | |||
// 4x6 Keypad | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint8_t keymaps[KEYMAPS_COUNT][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | |||
#else | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
#endif | |||
/* Keymap 0: Default Layer | |||
* ,---------------. | |||
* |Esc|Fn0|Fn1|Fn2| | |||
* |---+---+---+---| | |||
* |Num|/ |* |- | | |||
* |---+---+---+---| | |||
* |7 |8 |9 |+ | | |||
* |---+---+---| | | |||
* |4 |5 |6 | | | |||
* |---+---+---+---| | |||
* |1 |2 |3 |Ent| | |||
* |---+---+---| | | |||
* |0 |. | | | |||
* `---------------' | |||
*/ | |||
[0] = KEYMAP( | |||
ESC, FN0, FN1, FN2, \ | |||
NLCK,PSLS,PAST,PMNS, \ | |||
P7, P8, P9, PPLS, \ | |||
P4, P5, P6, PENT, \ | |||
P1, P2, P3, PENT, \ | |||
P0, NO, PDOT,NO) | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint16_t fn_actions[FN_ACTIONS_COUNT] __attribute__ ((section (".keymap.fn_actions"))) = { | |||
#else | |||
const uint16_t fn_actions[] PROGMEM = { | |||
#endif | |||
[0] = ACTION_BACKLIGHT_TOGGLE(), | |||
[1] = ACTION_BACKLIGHT_DECREASE(), | |||
[2] = ACTION_BACKLIGHT_INCREASE() | |||
}; | |||
#ifdef KEYMAP_EX_ENABLE | |||
uint16_t keys_count(void) { | |||
return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_ROWS * MATRIX_COLS; | |||
} | |||
uint16_t fn_actions_count(void) { | |||
return sizeof(fn_actions) / sizeof(fn_actions[0]); | |||
} | |||
#endif |
@@ -0,0 +1,62 @@ | |||
#include "keymap_common.h" | |||
// Keypad with Arrow | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint8_t keymaps[KEYMAPS_COUNT][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | |||
#else | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
#endif | |||
/* Keymap 0: Default Layer | |||
* ,---------------. | |||
* |Num|/ |* |- | | |||
* |---+---+---+---| | |||
* |7 |8 |9 |+ | | |||
* |---+---+---| | | |||
* |4 |5 |6 | | | |||
* |---+---+---+---| | |||
* |1 |2 |3 |Ent| | |||
* |---+---+---| | | |||
* |0 |Up |. | | | |||
* |---+---+---+---| | |||
* |Lef|Dow|Rig|Fn0| | |||
* `---------------' | |||
*/ | |||
[0] = KEYMAP( | |||
NLCK,PSLS,PAST,PMNS, \ | |||
P7, P8, P9, PPLS, \ | |||
P4, P5, P6, NO, \ | |||
P1, P2, P3, PENT, \ | |||
P0, UP, PDOT,NO, \ | |||
LEFT,DOWN,RGHT,FN0), | |||
/* Keymap 1: */ | |||
[1] = KEYMAP( | |||
TRNS,TRNS,TRNS,TRNS, \ | |||
TRNS,TRNS,TRNS,TRNS, \ | |||
TRNS,TRNS,TRNS,TRNS, \ | |||
TRNS,TRNS,TRNS,TRNS, \ | |||
TRNS,TRNS,TRNS,TRNS, \ | |||
FN1, TRNS,FN2, TRNS), | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint16_t fn_actions[FN_ACTIONS_COUNT] __attribute__ ((section (".keymap.fn_actions"))) = { | |||
#else | |||
const uint16_t fn_actions[] PROGMEM = { | |||
#endif | |||
[0] = ACTION_LAYER_MOMENTARY(1), | |||
[1] = ACTION_BACKLIGHT_DECREASE(), | |||
[2] = ACTION_BACKLIGHT_INCREASE() | |||
}; | |||
#ifdef KEYMAP_EX_ENABLE | |||
uint16_t keys_count(void) { | |||
return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_ROWS * MATRIX_COLS; | |||
} | |||
uint16_t fn_actions_count(void) { | |||
return sizeof(fn_actions) / sizeof(fn_actions[0]); | |||
} | |||
#endif |
@@ -0,0 +1,49 @@ | |||
/* | |||
Copyright 2012,2013 Jun Wako <[email protected]> | |||
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 "keymap_common.h" | |||
/* translates key to keycode */ | |||
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key) | |||
{ | |||
#ifndef KEYMAP_EX_ENABLE | |||
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); | |||
#else | |||
return eeconfig_read_keymap_key(layer, key.row, key.col); | |||
#endif | |||
} | |||
/* translates Fn keycode to action */ | |||
action_t keymap_fn_to_action(uint8_t keycode) | |||
{ | |||
return (action_t) { | |||
#ifndef KEYMAP_EX_ENABLE | |||
.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]) | |||
#else | |||
.code = eeconfig_read_keymap_fn_action(FN_INDEX(keycode)) | |||
#endif | |||
}; | |||
} | |||
#ifdef KEYMAP_EX_ENABLE | |||
const uint8_t* keymaps_pointer(void) { | |||
return (const uint8_t*)keymaps; | |||
} | |||
const uint16_t* fn_actions_pointer(void) { | |||
return fn_actions; | |||
} | |||
#endif |
@@ -0,0 +1,54 @@ | |||
/* | |||
Copyright 2012,2013 Jun Wako <[email protected]> | |||
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_COMMON_H | |||
#define KEYMAP_COMMON_H | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
#include <avr/pgmspace.h> | |||
#include "keycode.h" | |||
#include "action.h" | |||
#include "action_macro.h" | |||
#include "report.h" | |||
#include "host.h" | |||
#include "print.h" | |||
#include "debug.h" | |||
#include "keymap.h" | |||
#include "keymap_ex.h" | |||
extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; | |||
extern const uint16_t fn_actions[]; | |||
/* GHPad keymap definition macro | |||
*/ | |||
#define KEYMAP( \ | |||
K0A, K0B, K0C, K0D, \ | |||
K1A, K1B, K1C, K1D, \ | |||
K2A, K2B, K2C, K2D, \ | |||
K3A, K3B, K3C, K3D, \ | |||
K4A, K4B, K4C, K4D, \ | |||
K5A, K5B, K5C, K5D \ | |||
) { \ | |||
{ KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D }, \ | |||
{ KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D }, \ | |||
{ KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D }, \ | |||
{ KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D }, \ | |||
{ KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D }, \ | |||
{ KC_##K5A, KC_##K5B, KC_##K5C, KC_##K5D } \ | |||
} | |||
#endif |
@@ -0,0 +1,52 @@ | |||
#include "keymap_common.h" | |||
// 4x6 Keypad | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint8_t keymaps[KEYMAPS_COUNT][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | |||
#else | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
#endif | |||
/* Keymap 0: Default Layer | |||
* ,---------------. | |||
* |Esc|F5 |Fn0|BS | | |||
* |---+---+---+---| | |||
* |Num|/ |* |- | | |||
* |---+---+---+---| | |||
* |7 |8 |9 |+ | | |||
* |---+---+---| | | |||
* |4 |5 |6 | | | |||
* |---+---+---+---| | |||
* |1 |2 |3 |Ent| | |||
* |---+---+---| | | |||
* |0 |. | | | |||
* `---------------' | |||
*/ | |||
[0] = KEYMAP( | |||
ESC, F5, FN0, BSPC, \ | |||
NLCK,PSLS,PAST,PMNS, \ | |||
P7, P8, P9, PPLS, \ | |||
P4, P5, P6, PENT, \ | |||
P1, P2, P3, PENT, \ | |||
P0, NO, PDOT,NO) | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint16_t fn_actions[FN_ACTIONS_COUNT] __attribute__ ((section (".keymap.fn_actions"))) = { | |||
#else | |||
const uint16_t fn_actions[] PROGMEM = { | |||
#endif | |||
[0] = ACTION_BACKLIGHT_STEP(), | |||
}; | |||
#ifdef KEYMAP_EX_ENABLE | |||
uint16_t keys_count(void) { | |||
return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_ROWS * MATRIX_COLS; | |||
} | |||
uint16_t fn_actions_count(void) { | |||
return sizeof(fn_actions) / sizeof(fn_actions[0]); | |||
} | |||
#endif |
@@ -0,0 +1,34 @@ | |||
/* | |||
Copyright 2012 Jun Wako <[email protected]> | |||
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 "stdint.h" | |||
#include "led.h" | |||
void led_set(uint8_t usb_led) | |||
{ | |||
if (usb_led & (1<<USB_LED_NUM_LOCK)) { | |||
// output low | |||
DDRB |= (1<<PB2); | |||
PORTB &= ~(1<<PB2); | |||
} else { | |||
// Hi-Z | |||
DDRB &= ~(1<<PB2); | |||
PORTB &= ~(1<<PB2); | |||
} | |||
} |
@@ -0,0 +1,212 @@ | |||
/* | |||
Copyright 2013,2014 Kai Ryu <[email protected]> | |||
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/>. | |||
*/ | |||
/* | |||
* scan matrix | |||
*/ | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
#include "print.h" | |||
#include "debug.h" | |||
#include "util.h" | |||
#include "matrix.h" | |||
#ifndef DEBOUNCE | |||
# define DEBOUNCE 5 | |||
#endif | |||
static uint8_t debouncing = DEBOUNCE; | |||
/* matrix state(1:on, 0:off) */ | |||
static matrix_row_t matrix[MATRIX_ROWS]; | |||
static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | |||
static matrix_row_t read_cols(void); | |||
static void init_cols(void); | |||
static void unselect_rows(void); | |||
static void select_row(uint8_t row); | |||
inline | |||
uint8_t matrix_rows(void) | |||
{ | |||
return MATRIX_ROWS; | |||
} | |||
inline | |||
uint8_t matrix_cols(void) | |||
{ | |||
return MATRIX_COLS; | |||
} | |||
void matrix_init(void) | |||
{ | |||
// disable JTAG | |||
MCUCR = (1<<JTD); | |||
MCUCR = (1<<JTD); | |||
// initialize row and col | |||
unselect_rows(); | |||
init_cols(); | |||
// initialize matrix state: all keys off | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||
matrix[i] = 0; | |||
matrix_debouncing[i] = 0; | |||
} | |||
} | |||
uint8_t matrix_scan(void) | |||
{ | |||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||
select_row(i); | |||
_delay_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"); | |||
} | |||
debouncing = DEBOUNCE; | |||
} | |||
unselect_rows(); | |||
} | |||
if (debouncing) { | |||
if (--debouncing) { | |||
_delay_ms(1); | |||
} else { | |||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||
matrix[i] = matrix_debouncing[i]; | |||
} | |||
} | |||
} | |||
return 1; | |||
} | |||
bool matrix_is_modified(void) | |||
{ | |||
if (debouncing) return false; | |||
return true; | |||
} | |||
inline | |||
bool matrix_is_on(uint8_t row, uint8_t col) | |||
{ | |||
return (matrix[row] & ((matrix_row_t)1<<col)); | |||
} | |||
inline | |||
matrix_row_t matrix_get_row(uint8_t row) | |||
{ | |||
return matrix[row]; | |||
} | |||
void matrix_print(void) | |||
{ | |||
print("\nr/c 0123456789ABCDEF\n"); | |||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | |||
phex(row); print(": "); | |||
pbin_reverse16(matrix_get_row(row)); | |||
print("\n"); | |||
} | |||
} | |||
uint8_t matrix_key_count(void) | |||
{ | |||
uint8_t count = 0; | |||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||
count += bitpop16(matrix[i]); | |||
} | |||
return count; | |||
} | |||
/* Column pin configuration | |||
* col: 0 1 2 3 | |||
* pin: F0 F1 E6 C7 | |||
*/ | |||
static void init_cols(void) | |||
{ | |||
// Input with pull-up(DDR:0, PORT:1) | |||
DDRF &= ~(1<<PF1 | 1<<PF0); | |||
PORTF |= (1<<PF1 | 1<<PF0); | |||
DDRE &= ~(1<<PE6); | |||
PORTE |= (1<<PE6); | |||
DDRC &= ~(1<<PC7); | |||
PORTC |= (1<<PC7); | |||
} | |||
/* Column pin configuration | |||
* col: 0 1 2 3 | |||
* pin: F0 F1 E6 C7 | |||
*/ | |||
static matrix_row_t read_cols(void) | |||
{ | |||
return (PINF&(1<<PF0) ? 0 : (1<<0)) | | |||
(PINF&(1<<PF1) ? 0 : (1<<1)) | | |||
(PINE&(1<<PE6) ? 0 : (1<<2)) | | |||
(PINC&(1<<PC7) ? 0 : (1<<3)); | |||
} | |||
/* Row pin configuration | |||
* row: 0 1 2 3 4 5 | |||
* pin: D0 D1 D2 D3 D4 D5 | |||
*/ | |||
static void unselect_rows(void) | |||
{ | |||
// Hi-Z(DDR:0, PORT:0) to unselect | |||
DDRD &= ~0b00111111; | |||
PORTD &= ~0b00111111; | |||
} | |||
/* Row pin configuration | |||
* row: 0 1 2 3 4 5 | |||
* pin: D0 D1 D2 D3 D4 D5 | |||
*/ | |||
static void select_row(uint8_t row) | |||
{ | |||
// Output low(DDR:1, PORT:0) to select | |||
switch (row) { | |||
case 0: | |||
DDRD |= (1<<0); | |||
PORTD &= ~(1<<0); | |||
break; | |||
case 1: | |||
DDRD |= (1<<1); | |||
PORTD &= ~(1<<1); | |||
break; | |||
case 2: | |||
DDRD |= (1<<2); | |||
PORTD &= ~(1<<2); | |||
break; | |||
case 3: | |||
DDRD |= (1<<3); | |||
PORTD &= ~(1<<3); | |||
break; | |||
case 4: | |||
DDRD |= (1<<4); | |||
PORTD &= ~(1<<4); | |||
break; | |||
case 5: | |||
DDRD |= (1<<5); | |||
PORTD &= ~(1<<5); | |||
break; | |||
} | |||
} |
@@ -102,7 +102,7 @@ ARCH = AVR8 | |||
F_USB = $(F_CPU) | |||
# Interrupt driven control endpoint task | |||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
# Boot Section Size in *bytes* |
@@ -25,7 +25,7 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ | |||
LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,FN4, \ | |||
FN5, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ | |||
FN11,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ | |||
LGUI,LALT, FN6, RALT,RGUI), | |||
/* Layer 1: HHKB mode (HHKB Fn) | |||
@@ -131,12 +131,9 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
/* id for user defined functions */ | |||
enum function_id { | |||
LSHIFT_LPAREN, | |||
RSHIFT_RPAREN, | |||
}; | |||
enum macro_id { | |||
LSHIFT_PAREN, | |||
RSHIFT_PAREN, | |||
HELLO, | |||
VOLUP, | |||
}; | |||
@@ -163,10 +160,7 @@ const uint16_t fn_actions[] PROGMEM = { | |||
// [8] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // LControl with tap Backspace | |||
// [9] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC), // LControl with tap Esc | |||
[11] = ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // Function: LShift with tap '(' | |||
[12] = ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // Function: RShift with tap ')' | |||
// [13] = ACTION_MACRO_TAP(LSHIFT_PAREN), // Macro: LShift with tap '(' | |||
// [14] = ACTION_MACRO_TAP(RSHIFT_PAREN), // Macro: RShift with tap ')' | |||
[11] = ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // Function: LShift with tap '(' | |||
// [15] = ACTION_MACRO(HELLO), // Macro: say hello | |||
// [9] = ACTION_MACRO(VOLUP), // Macro: media key | |||
}; | |||
@@ -177,32 +171,13 @@ const uint16_t fn_actions[] PROGMEM = { | |||
*/ | |||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||
{ | |||
keyevent_t event = record->event; | |||
tap_t tap = record->tap; | |||
switch (id) { | |||
case LSHIFT_PAREN: | |||
if (tap.count > 0 && !tap.interrupted) { | |||
return (event.pressed ? | |||
MACRO( D(LSHIFT), D(9), U(9), U(LSHIFT), END ) : MACRO_NONE); | |||
} else { | |||
return (event.pressed ? | |||
MACRO( D(LSHIFT), END ) : MACRO( U(LSHIFT), END ) ); | |||
} | |||
case RSHIFT_PAREN: | |||
if (tap.count > 0 && !tap.interrupted) { | |||
return (event.pressed ? | |||
MACRO( D(RSHIFT), D(0), U(0), U(RSHIFT), END ) : MACRO_NONE); | |||
} else { | |||
return (event.pressed ? | |||
MACRO( D(RSHIFT), END ) : MACRO( U(RSHIFT), END ) ); | |||
} | |||
case HELLO: | |||
return (event.pressed ? | |||
return (record->event.pressed ? | |||
MACRO( I(0), T(H), T(E), T(L), T(L), W(255), T(O), END ) : | |||
MACRO_NONE ); | |||
case VOLUP: | |||
return (event.pressed ? | |||
return (record->event.pressed ? | |||
MACRO( D(VOLU), U(VOLU), END ) : | |||
MACRO_NONE ); | |||
} | |||
@@ -216,48 +191,36 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||
*/ | |||
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) | |||
{ | |||
keyevent_t event = record->event; | |||
tap_t tap = record->tap; | |||
if (record->event.pressed) dprint("P"); else dprint("R"); | |||
dprintf("%d", record->tap.count); | |||
if (record->tap.interrupted) dprint("i"); | |||
dprint("\n"); | |||
switch (id) { | |||
case LSHIFT_LPAREN: | |||
// LShft + tap '(' | |||
// NOTE: cant use register_code to avoid conflicting with magic key bind | |||
if (event.pressed) { | |||
if (tap.count == 0 || tap.interrupted) { | |||
//add_mods(MOD_BIT(KC_LSHIFT)); | |||
layer_on(1); | |||
// Shift parentheses example: LShft + tap '(' | |||
// http://stevelosh.com/blog/2012/10/a-modern-space-cadet/#shift-parentheses | |||
// http://geekhack.org/index.php?topic=41989.msg1304899#msg1304899 | |||
if (record->event.pressed) { | |||
if (record->tap.count > 0 && !record->tap.interrupted) { | |||
if (record->tap.interrupted) { | |||
dprint("tap interrupted\n"); | |||
register_mods(MOD_BIT(KC_LSHIFT)); | |||
} | |||
} else { | |||
add_mods(MOD_BIT(KC_LSHIFT)); | |||
add_key(KC_9); | |||
send_keyboard_report(); | |||
del_mods(MOD_BIT(KC_LSHIFT)); | |||
del_key(KC_9); | |||
send_keyboard_report(); | |||
register_mods(MOD_BIT(KC_LSHIFT)); | |||
} | |||
} else { | |||
if (tap.count == 0 || tap.interrupted) { | |||
//del_mods(MOD_BIT(KC_LSHIFT)); | |||
layer_off(1); | |||
} | |||
} | |||
break; | |||
case RSHIFT_RPAREN: | |||
// RShift + tap ')' | |||
if (event.pressed) { | |||
if (tap.count == 0 || tap.interrupted) { | |||
add_mods(MOD_BIT(KC_RSHIFT)); | |||
} else { | |||
add_mods(MOD_BIT(KC_RSHIFT)); | |||
add_key(KC_0); | |||
if (record->tap.count > 0 && !(record->tap.interrupted)) { | |||
add_weak_mods(MOD_BIT(KC_LSHIFT)); | |||
send_keyboard_report(); | |||
del_mods(MOD_BIT(KC_RSHIFT)); | |||
del_key(KC_0); | |||
register_code(KC_9); | |||
unregister_code(KC_9); | |||
del_weak_mods(MOD_BIT(KC_LSHIFT)); | |||
send_keyboard_report(); | |||
} | |||
} else { | |||
if (tap.count == 0 || tap.interrupted) { | |||
del_mods(MOD_BIT(KC_RSHIFT)); | |||
record->tap.count = 0; // ad hoc: cancel tap | |||
} else { | |||
unregister_mods(MOD_BIT(KC_LSHIFT)); | |||
} | |||
} | |||
break; |
@@ -0,0 +1,126 @@ | |||
#---------------------------------------------------------------------------- | |||
# On command line: | |||
# | |||
# make all = Make software. | |||
# | |||
# make clean = Clean out built project files. | |||
# | |||
# make coff = Convert ELF to AVR COFF. | |||
# | |||
# make extcoff = Convert ELF to AVR Extended COFF. | |||
# | |||
# make program = Download the hex file to the device. | |||
# Please customize your programmer settings(PROGRAM_CMD) | |||
# | |||
# make teensy = Download the hex file to the device, using teensy_loader_cli. | |||
# (must have teensy_loader_cli installed). | |||
# | |||
# make dfu = Download the hex file to the device, using dfu-programmer (must | |||
# have dfu-programmer installed). | |||
# | |||
# make flip = Download the hex file to the device, using Atmel FLIP (must | |||
# have Atmel FLIP installed). | |||
# | |||
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer | |||
# (must have dfu-programmer installed). | |||
# | |||
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP | |||
# (must have Atmel FLIP installed). | |||
# | |||
# make debug = Start either simulavr or avarice as specified for debugging, | |||
# with avr-gdb or avr-insight as the front end for debugging. | |||
# | |||
# make filename.s = Just compile filename.c into the assembler code only. | |||
# | |||
# make filename.i = Create a preprocessed source file for use in submitting | |||
# bug reports to the GCC project. | |||
# | |||
# To rebuild project do "make clean" then "make all". | |||
#---------------------------------------------------------------------------- | |||
# Target file name (without extension). | |||
TARGET = lightsaber_lufa | |||
# Directory common source filess exist | |||
TOP_DIR = ../.. | |||
# Directory keyboard dependent files exist | |||
TARGET_DIR = . | |||
# List C source files here. (C dependencies are automatically generated.) | |||
SRC = keymap.c \ | |||
matrix.c \ | |||
led.c \ | |||
backlight.c | |||
CONFIG_H = config.h | |||
# MCU name | |||
MCU = atmega32u4 | |||
# Processor frequency. | |||
# This will define a symbol, F_CPU, in all source code files equal to the | |||
# processor frequency in Hz. You can then use this symbol in your source code to | |||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done | |||
# automatically to create a 32-bit value in your source code. | |||
# | |||
# This will be an integer division of F_USB below, as it is sourced by | |||
# F_USB after it has run through any CPU prescalers. Note that this value | |||
# does not *change* the processor frequency - it should merely be updated to | |||
# reflect the processor speed set externally so that the code can use accurate | |||
# software delays. | |||
F_CPU = 8000000 | |||
# | |||
# LUFA specific | |||
# | |||
# Target architecture (see library "Board Types" documentation). | |||
ARCH = AVR8 | |||
# Input clock frequency. | |||
# This will define a symbol, F_USB, in all source code files equal to the | |||
# input clock frequency (before any prescaling is performed) in Hz. This value may | |||
# differ from F_CPU if prescaling is used on the latter, and is required as the | |||
# raw input clock is fed directly to the PLL sections of the AVR for high speed | |||
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' | |||
# at the end, this will be done automatically to create a 32-bit value in your | |||
# source code. | |||
# | |||
# If no clock division is performed on the input clock inside the AVR (via the | |||
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. | |||
F_USB = $(F_CPU) | |||
# Build Options | |||
# comment out to disable the options. | |||
# | |||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
#MOUSEKEY_ENABLE = yes # Mouse keys(+4700) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450) | |||
CONSOLE_ENABLE = yes # Console for debug(+400) | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||
#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA | |||
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality | |||
# Boot Section Size in bytes | |||
# Teensy halfKay 512 | |||
# Atmel DFU loader 4096 | |||
# LUFA bootloader 4096 | |||
OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/lufa.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk | |||
winkey: OPT_DEFS += -DLAYOUT_WINKEY | |||
winkey: all |
@@ -0,0 +1,94 @@ | |||
#---------------------------------------------------------------------------- | |||
# On command line: | |||
# | |||
# make all = Make software. | |||
# | |||
# make clean = Clean out built project files. | |||
# | |||
# make coff = Convert ELF to AVR COFF. | |||
# | |||
# make extcoff = Convert ELF to AVR Extended COFF. | |||
# | |||
# make program = Download the hex file to the device. | |||
# Please customize your programmer settings(PROGRAM_CMD) | |||
# | |||
# make teensy = Download the hex file to the device, using teensy_loader_cli. | |||
# (must have teensy_loader_cli installed). | |||
# | |||
# make dfu = Download the hex file to the device, using dfu-programmer (must | |||
# have dfu-programmer installed). | |||
# | |||
# make flip = Download the hex file to the device, using Atmel FLIP (must | |||
# have Atmel FLIP installed). | |||
# | |||
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer | |||
# (must have dfu-programmer installed). | |||
# | |||
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP | |||
# (must have Atmel FLIP installed). | |||
# | |||
# make debug = Start either simulavr or avarice as specified for debugging, | |||
# with avr-gdb or avr-insight as the front end for debugging. | |||
# | |||
# make filename.s = Just compile filename.c into the assembler code only. | |||
# | |||
# make filename.i = Create a preprocessed source file for use in submitting | |||
# bug reports to the GCC project. | |||
# | |||
# To rebuild project do "make clean" then "make all". | |||
#---------------------------------------------------------------------------- | |||
# Target file name (without extension). | |||
TARGET = lightsaber_pjrc | |||
# Directory common source filess exist | |||
TOP_DIR = ../.. | |||
# Directory keyboard dependent files exist | |||
TARGET_DIR = . | |||
# keyboard dependent files | |||
SRC = keymap.c \ | |||
matrix.c \ | |||
led.c \ | |||
backlight.c | |||
CONFIG_H = config.h | |||
# MCU name | |||
MCU = atmega32u4 | |||
# Processor frequency. | |||
# Normally the first thing your program should do is set the clock prescaler, | |||
# so your program will run at the correct speed. You should also set this | |||
# variable to same clock speed. The _delay_ms() macro uses this, and many | |||
# examples use this variable to calculate timings. Do not add a "UL" here. | |||
F_CPU = 8000000 | |||
# Build Options | |||
# comment out to disable the options. | |||
# | |||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
#MOUSEKEY_ENABLE = yes # Mouse keys(+5000) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+600) | |||
CONSOLE_ENABLE = yes # Console for debug | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||
#NKRO_ENABLE = yes # USB Nkey Rollover(+500) | |||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/pjrc.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk | |||
winkey: OPT_DEFS += -DLAYOUT_WINKEY | |||
winkey: all |
@@ -0,0 +1,26 @@ | |||
Lightsaber keyboard firmware | |||
====================== | |||
Korean custom keyboard designed by Duck. | |||
*Note that this is not the official firmware* | |||
Supported models | |||
---------------- | |||
All pcb options are supported. | |||
Build | |||
----- | |||
Move to this directory then just run `make` like: | |||
$ make -f Makefile.[pjrc|lufa] | |||
Use `Makefile.pjrc` if you want to use PJRC stack or use `Makefile.lufa` for LUFA stack. | |||
Bootloader | |||
--------- | |||
The PCB is hardwired to run the bootloader if the key at the `one above backspace` position is held down when connecting the keyboard. | |||
It is still possible to use Boot Magic and Command to access the bootloader though. | |||
@@ -0,0 +1,86 @@ | |||
/* | |||
Copyright 2014 Ralf Schmitt <[email protected]> | |||
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 "backlight.h" | |||
/* Backlight pin configuration | |||
* | |||
* Alphas PB1 (high) | |||
* Numeric PB2 (high) | |||
* Mod+Num PB3 (high) | |||
* Backside PD6 (high) | |||
* TopRight PD7 (low) | |||
* F-Row PE6 (high) | |||
*/ | |||
void backlight_set(uint8_t level) | |||
{ | |||
// Set as output. | |||
DDRB |= (1<<1) | (1<<2) | (1<<3); | |||
DDRD |= (1<<6) | (1<<7); | |||
DDRE |= (1<<6); | |||
if (level & BACKLIGHT_ALPHA) | |||
{ | |||
PORTB |= (1<<1); | |||
} | |||
else | |||
{ | |||
PORTB &= ~(1<<1); | |||
} | |||
if (level & BACKLIGHT_NUMERIC) | |||
{ | |||
PORTB |= (1<<2); | |||
} | |||
else | |||
{ | |||
PORTB &= ~(1<<2); | |||
} | |||
if (level & BACKLIGHT_MODNUM) | |||
{ | |||
PORTB |= (1<<3); | |||
} | |||
else | |||
{ | |||
PORTB &= ~(1<<3); | |||
} | |||
if (level & BACKLIGHT_BACKSIDE) | |||
{ | |||
PORTD |= (1<<6); | |||
} | |||
else | |||
{ | |||
PORTD &= ~(1<<6); | |||
} | |||
if (level & BACKLIGHT_TOPRIGHT) | |||
{ | |||
PORTD &= ~(1<<7); | |||
} | |||
else | |||
{ | |||
PORTD |= (1<<7); | |||
} | |||
if (level & BACKLIGHT_FROW) | |||
{ | |||
PORTE |= (1<<6); | |||
} | |||
else | |||
{ | |||
PORTE &= ~(1<<6); | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
enum backlight_level { | |||
BACKLIGHT_ALPHA = 0b0000001, | |||
BACKLIGHT_NUMERIC = 0b0000010, | |||
BACKLIGHT_MODNUM = 0b0000100, | |||
BACKLIGHT_BACKSIDE = 0b0001000, | |||
BACKLIGHT_TOPRIGHT = 0b0010000, | |||
BACKLIGHT_FROW = 0b0100000, | |||
}; |
@@ -0,0 +1,46 @@ | |||
/* | |||
Copyright 2013 Mathias Andersson <[email protected]> | |||
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_H | |||
#define CONFIG_H | |||
/* USB Device descriptor parameter */ | |||
#define VENDOR_ID 0xFEED | |||
#define PRODUCT_ID 0x6050 | |||
#define DEVICE_VER 0x0104 | |||
#define MANUFACTURER Duck | |||
#define PRODUCT Lightsaber | |||
/* message strings */ | |||
#define DESCRIPTION t.m.k. keyboard firmware for Lightsaber | |||
/* matrix size */ | |||
#define MATRIX_ROWS 6 | |||
#define MATRIX_COLS 18 | |||
/* number of backlight levels */ | |||
#define BACKLIGHT_LEVELS 1 | |||
/* Set 0 if need no debouncing */ | |||
#define DEBOUNCE 5 | |||
/* key combination for command */ | |||
#define IS_COMMAND() ( \ | |||
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ | |||
) | |||
#endif |
@@ -0,0 +1,77 @@ | |||
/* | |||
Copyright 2014 Ralf Schmitt <[email protected]> | |||
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 for Lightsaber controller | |||
*/ | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
#include <avr/pgmspace.h> | |||
#include "keycode.h" | |||
#include "action.h" | |||
#include "action_macro.h" | |||
#include "report.h" | |||
#include "host.h" | |||
#include "debug.h" | |||
#include "keymap.h" | |||
// Convert physical keyboard layout to matrix array. | |||
// This is a macro to define keymap easily in keyboard layout form. | |||
#define KEYMAP( \ | |||
K5A, K5B, K5C, K5D, K5E, K5F, K5G, K5H, K5I, K5J, K5K, K5L, K5M, K5N, K5O, K5P, K5Q, K5R, \ | |||
K4A, K4B, K4C, K4D, K4E, K4F, K4G, K4H, K4I, K4J, K4K, K4L, K4M, K4N, K4O, K4P, K4Q, K4R, \ | |||
K3A, K3B, K3C, K3D, K3E, K3F, K3G, K3H, K3I, K3J, K3K, K3L, K3M, K3N, K3O, K3P, K3Q, K3R, \ | |||
K2A, K2B, K2C, K2D, K2E, K2F, K2G, K2H, K2I, K2J, K2K, K2L, K2M, K2N, K2O, K2P, K2Q, K2R, \ | |||
K1A, K1C, K1D, K1E, K1F, K1G, K1H, K1I, K1J, K1K, K1L, K1M, K1N, K1O, K1P, K1Q, K1R, \ | |||
K0A, K0B, K0C, K0G, K0K, K0L, K0M, K0N, K0O, K0P, K0Q, K0R \ | |||
) { \ | |||
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 */ \ | |||
/* 5 */ { KC_##K5A, KC_##K5B, KC_##K5C, KC_##K5D, KC_##K5E, KC_##K5F, KC_##K5G, KC_##K5H, KC_##K5I, KC_##K5J, KC_##K5K, KC_##K5L, KC_##K5M, KC_##K5N, KC_##K5O, KC_##K5P, KC_##K5Q, KC_##K5R}, \ | |||
/* 4 */ { KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_##K4F, KC_##K4G, KC_##K4H, KC_##K4I, KC_##K4J, KC_##K4K, KC_##K4L, KC_##K4M, KC_##K4N, KC_##K4O, KC_##K4P, KC_##K4Q, KC_##K4R}, \ | |||
/* 3 */ { KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F, KC_##K3G, KC_##K3H, KC_##K3I, KC_##K3J, KC_##K3K, KC_##K3L, KC_##K3M, KC_##K3N, KC_##K3O, KC_##K3P, KC_##K3Q, KC_##K3R}, \ | |||
/* 2 */ { KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F, KC_##K2G, KC_##K2H, KC_##K2I, KC_##K2J, KC_##K2K, KC_##K2L, KC_##K2M, KC_##K2N, KC_##K2O, KC_##K2P, KC_##K2Q, KC_##K2R}, \ | |||
/* 1 */ { KC_##K1A, KC_##K1C, KC_##K1D, KC_##K1E, KC_##K1F, KC_##K1G, KC_##K1H, KC_##K1I, KC_##K1J, KC_##K1K, KC_##K1L, KC_NO, KC_##K1M, KC_##K1N, KC_##K1O, KC_##K1P, KC_##K1Q, KC_##K1R}, \ | |||
/* 0 */ { KC_##K0A, KC_##K0B, KC_##K0C, KC_NO, KC_NO, KC_##K0G, KC_NO, KC_NO, KC_##K0K, KC_NO, KC_##K0L, KC_NO, KC_##K0M, KC_##K0N, KC_##K0O, KC_##K0P, KC_##K0Q, KC_##K0R} \ | |||
} | |||
#include "keymap_winkey.h" | |||
#define KEYMAPS_SIZE (sizeof(keymaps) / sizeof(keymaps[0])) | |||
#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0])) | |||
/* translates key to keycode */ | |||
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key) | |||
{ | |||
if (layer < KEYMAPS_SIZE) { | |||
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); | |||
} else { | |||
// fall back to layer 0 | |||
return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]); | |||
} | |||
} | |||
/* translates Fn keycode to action */ | |||
action_t keymap_fn_to_action(uint8_t keycode) | |||
{ | |||
action_t action; | |||
if (FN_INDEX(keycode) < FN_ACTIONS_SIZE) { | |||
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]); | |||
} else { | |||
action.code = ACTION_NO; | |||
} | |||
return action; | |||
} |
@@ -0,0 +1,29 @@ | |||
#include "backlight.h" | |||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
KEYMAP(\ | |||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, INS, PSCR, SLCK, BRK, \ | |||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, NUMLOCK,KP_SLASH,KP_ASTERISK,KP_MINUS, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, KP_7, KP_8, KP_9, KP_PLUS, \ | |||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,FN0, ENT, KP_4, KP_5, KP_6, NO, \ | |||
LSFT, Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, RSFT, KP_1, KP_2, KP_3, KP_ENTER, \ | |||
LCTL,LGUI,LALT, SPC, NO, RALT,RGUI,RCTL, KP_0, NO, KP_DOT, NO), \ | |||
KEYMAP(\ | |||
CALC,MYCM,WSCH,WHOM,MAIL,MUTE,VOLD,VOLU,MSEL,MSTP,MPLY,MPRV,MNXT,TRNS, TRNS, WAKE, PWR, SLEP, \ | |||
FN1, FN2, FN3, FN4, FN5, FN6, FN7, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, \ | |||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, \ | |||
TRNS,TRNS,TRNS,TRNS,PGDN,TRNS,LEFT,DOWN,UP ,RGHT,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, \ | |||
TRNS, TRNS,TRNS,TRNS,TRNS,PGUP,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, \ | |||
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS) | |||
}; | |||
static const uint16_t PROGMEM fn_actions[] = { | |||
[0] = ACTION_LAYER_MOMENTARY(1), | |||
[1] = ACTION_BACKLIGHT_TOGGLE(), | |||
[2] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_ALPHA), | |||
[3] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_MODNUM), | |||
[4] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_NUMERIC), | |||
[5] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_FROW), | |||
[6] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_BACKSIDE), | |||
[7] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_TOPRIGHT) | |||
}; |
@@ -0,0 +1,54 @@ | |||
/* | |||
Copyright 2014 Ralf Schmitt <[email protected]> | |||
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 "stdint.h" | |||
#include "led.h" | |||
/* LED pin configuration | |||
* | |||
* Caps PB0 (low) | |||
* NumLock PB4 (low) | |||
* | |||
*/ | |||
void led_set(uint8_t usb_led) | |||
{ | |||
// Set as output. | |||
DDRB |= (1<<0) | (1<<4); | |||
if (usb_led & (1<<USB_LED_CAPS_LOCK)) | |||
{ | |||
// Output low. | |||
PORTB &= ~(1<<0); | |||
} | |||
else | |||
{ | |||
// Output high. | |||
PORTB |= (1<<0); | |||
} | |||
if (usb_led & (1<<USB_LED_NUM_LOCK)) | |||
{ | |||
// Output low. | |||
PORTB &= ~(1<<4); | |||
} | |||
else | |||
{ | |||
// Output high. | |||
PORTB |= (1<<4); | |||
} | |||
} |
@@ -0,0 +1,292 @@ | |||
/* | |||
Copyright 2014 Ralf Schmitt <[email protected]> | |||
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> | |||
#include <util/delay.h> | |||
#include "print.h" | |||
#include "debug.h" | |||
#include "util.h" | |||
#include "matrix.h" | |||
#ifndef DEBOUNCE | |||
# define DEBOUNCE 0 | |||
#endif | |||
static uint8_t debouncing = DEBOUNCE; | |||
/* matrix state(1:on, 0:off) */ | |||
static matrix_row_t matrix[MATRIX_ROWS]; | |||
static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | |||
static uint8_t read_rows(void); | |||
static uint8_t read_fwkey(void); | |||
static void init_rows(void); | |||
static void unselect_cols(void); | |||
static void select_col(uint8_t col); | |||
inline | |||
uint8_t matrix_rows(void) | |||
{ | |||
return MATRIX_ROWS; | |||
} | |||
inline | |||
uint8_t matrix_cols(void) | |||
{ | |||
return MATRIX_COLS; | |||
} | |||
void matrix_init(void) | |||
{ | |||
unselect_cols(); | |||
init_rows(); | |||
// initialize matrix state: all keys off | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||
matrix[i] = 0; | |||
matrix_debouncing[i] = 0; | |||
} | |||
} | |||
uint8_t matrix_scan(void) | |||
{ | |||
for (uint8_t col = 0; col < MATRIX_COLS; col++) { // 0-17 | |||
select_col(col); | |||
_delay_us(3); // TODO: Determine the correct value needed here. | |||
uint8_t rows = read_rows(); | |||
// Use the otherwise unused col: 12 row: 3 for firmware. | |||
if(col == 12) { | |||
rows |= read_fwkey(); | |||
} | |||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) { // 0-5 | |||
bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); | |||
bool curr_bit = rows & (1<<row); | |||
if (prev_bit != curr_bit) { | |||
matrix_debouncing[row] ^= ((matrix_row_t)1<<col); | |||
if (debouncing) { | |||
dprint("bounce!: "); dprintf("%02X", debouncing); dprintln(); | |||
} | |||
debouncing = DEBOUNCE; | |||
} | |||
} | |||
unselect_cols(); | |||
} | |||
if (debouncing) { | |||
if (--debouncing) { | |||
_delay_ms(1); | |||
} else { | |||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||
matrix[i] = matrix_debouncing[i]; | |||
} | |||
} | |||
} | |||
return 1; | |||
} | |||
bool matrix_is_modified(void) | |||
{ | |||
if (debouncing) return false; | |||
return true; | |||
} | |||
inline | |||
bool matrix_is_on(uint8_t row, uint8_t col) | |||
{ | |||
return (matrix[row] & ((matrix_row_t)1<<col)); | |||
} | |||
inline | |||
matrix_row_t matrix_get_row(uint8_t row) | |||
{ | |||
return matrix[row]; | |||
} | |||
void matrix_print(void) | |||
{ | |||
print("\nr/c 0123456789ABCDEF\n"); | |||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | |||
xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row))); | |||
} | |||
} | |||
uint8_t matrix_key_count(void) | |||
{ | |||
uint8_t count = 0; | |||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||
count += bitpop32(matrix[i]); | |||
} | |||
return count; | |||
} | |||
/* Row pin configuration | |||
* row: 0 1 2 3 4 5 | |||
* pin: PD0 PD1 PD2 PD3 PD5 PB7 | |||
* | |||
* Firmware uses its own pin PE2 | |||
*/ | |||
static void init_rows(void) | |||
{ | |||
// Input (DDR:0, PORT:0) | |||
DDRD &= ~0b00101111; | |||
PORTD &= ~0b00101111; | |||
DDRB &= ~(1<<7); | |||
PORTB &= ~(1<<7); | |||
// Input with pull-up (DDR:0, PORT:1) | |||
DDRE &= ~(1<<2); | |||
PORTE |= (1<<2); | |||
} | |||
static uint8_t read_rows(void) | |||
{ | |||
return (PIND&(1<<0) ? (1<<0) : 0) | | |||
(PIND&(1<<1) ? (1<<1) : 0) | | |||
(PIND&(1<<2) ? (1<<2) : 0) | | |||
(PIND&(1<<3) ? (1<<3) : 0) | | |||
(PIND&(1<<5) ? (1<<4) : 0) | | |||
(PINB&(1<<7) ? (1<<5) : 0); | |||
} | |||
static uint8_t read_fwkey(void) | |||
{ | |||
return PINE&(1<<2) ? 0 : (1<<3); | |||
} | |||
/* Columns 0 - 15 | |||
* These columns uses two 74HC237D 3 to 8 bit demultiplexers. | |||
* col / pin: PC6 PB6 PF0 PF1 PC7 | |||
* 0: 1 0 0 0 0 | |||
* 1: 1 0 1 0 0 | |||
* 2: 1 0 0 1 0 | |||
* 3: 1 0 1 1 0 | |||
* 4: 1 0 0 0 1 | |||
* 5: 1 0 1 0 1 | |||
* 6: 1 0 0 1 1 | |||
* 7: 1 0 1 1 1 | |||
* 8: 0 1 0 0 0 | |||
* 9: 0 1 1 0 0 | |||
* 10: 0 1 0 1 0 | |||
* 11: 0 1 1 1 0 | |||
* 12: 0 1 0 0 1 | |||
* 13: 0 1 1 0 1 | |||
* 14: 0 1 0 1 1 | |||
* 15: 0 1 1 1 1 | |||
* | |||
* col: 16 | |||
* pin: PB5 | |||
* | |||
* col: 17 | |||
* pin: PD4 | |||
*/ | |||
static void unselect_cols(void) | |||
{ | |||
DDRB |= (1<<5) | (1<<6); | |||
PORTB &= ~((1<<5) | (1<<6)); | |||
DDRC |= (1<<6) | (1<<7); | |||
PORTC &= ~((1<<6) | (1<<7)); | |||
DDRD |= (1<<4); | |||
PORTD &= ~(1<<4); | |||
DDRF |= (1<<0) | (1<<1); | |||
PORTF &= ~((1<<0) | (1<<1)); | |||
} | |||
static void select_col(uint8_t col) | |||
{ | |||
// Output high (DDR:1, PORT:1) to select | |||
switch (col) { | |||
case 0: | |||
PORTC |= (1<<6); | |||
break; | |||
case 1: | |||
PORTC |= (1<<6); | |||
PORTF |= (1<<0); | |||
break; | |||
case 2: | |||
PORTC |= (1<<6); | |||
PORTF |= (1<<1); | |||
break; | |||
case 3: | |||
PORTC |= (1<<6); | |||
PORTF |= (1<<0) | (1<<1); | |||
break; | |||
case 4: | |||
PORTC |= (1<<6); | |||
PORTC |= (1<<7); | |||
break; | |||
case 5: | |||
PORTC |= (1<<6); | |||
PORTF |= (1<<0); | |||
PORTC |= (1<<7); | |||
break; | |||
case 6: | |||
PORTC |= (1<<6); | |||
PORTF |= (1<<1); | |||
PORTC |= (1<<7); | |||
break; | |||
case 7: | |||
PORTC |= (1<<6); | |||
PORTF |= (1<<0) | (1<<1); | |||
PORTC |= (1<<7); | |||
break; | |||
case 8: | |||
PORTB |= (1<<6); | |||
break; | |||
case 9: | |||
PORTB |= (1<<6); | |||
PORTF |= (1<<0); | |||
break; | |||
case 10: | |||
PORTB |= (1<<6); | |||
PORTF |= (1<<1); | |||
break; | |||
case 11: | |||
PORTB |= (1<<6); | |||
PORTF |= (1<<0) | (1<<1); | |||
break; | |||
case 12: | |||
PORTB |= (1<<6); | |||
PORTC |= (1<<7); | |||
break; | |||
case 13: | |||
PORTB |= (1<<6); | |||
PORTF |= (1<<0); | |||
PORTC |= (1<<7); | |||
break; | |||
case 14: | |||
PORTB |= (1<<6); | |||
PORTF |= (1<<1); | |||
PORTC |= (1<<7); | |||
break; | |||
case 15: | |||
PORTB |= (1<<6); | |||
PORTF |= (1<<0) | (1<<1); | |||
PORTC |= (1<<7); | |||
break; | |||
case 16: | |||
PORTB |= (1<<5); | |||
break; | |||
case 17: | |||
PORTD |= (1<<4); | |||
break; | |||
} | |||
} |
@@ -1,7 +1,12 @@ | |||
LUFA_DIR = protocol/lufa | |||
# Path to the LUFA library | |||
LUFA_PATH ?= protocol/lufa/LUFA-120730 | |||
ifeq (, $(wildcard $(TOP_DIR)/$(LUFA_DIR)/LUFA-git/LUFA/Version.h)) | |||
LUFA_PATH ?= $(LUFA_DIR)/LUFA-120730 | |||
else | |||
LUFA_PATH ?= $(LUFA_DIR)/LUFA-git | |||
endif | |||
# Create the LUFA source path variables by including the LUFA makefile | |||
ifneq (, $(wildcard $(TOP_DIR)/$(LUFA_PATH)/LUFA/Build/lufa_sources.mk)) | |||
@@ -30,9 +35,12 @@ VPATH += $(TOP_DIR)/$(LUFA_PATH) | |||
#endif | |||
# LUFA library compile-time options and predefined tokens | |||
LUFA_OPTS = -D USB_DEVICE_ONLY | |||
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS | |||
LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" | |||
LUFA_OPTS = -DUSB_DEVICE_ONLY | |||
LUFA_OPTS += -DUSE_FLASH_DESCRIPTORS | |||
LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" | |||
#LUFA_OPTS += -DINTERRUPT_CONTROL_ENDPOINT | |||
LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 | |||
LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1 | |||
OPT_DEFS += -DF_USB=$(F_USB)UL | |||
OPT_DEFS += -DARCH=ARCH_$(ARCH) |
@@ -0,0 +1 @@ | |||
Subproject commit b6c18b2a7c544653efbe12a1d4e8ba65e7d83c35 |
@@ -230,12 +230,12 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = | |||
{ | |||
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, | |||
.USBSpecification = VERSION_BCD(01.10), | |||
.USBSpecification = VERSION_BCD(1,1,0), | |||
.Class = USB_CSCP_NoDeviceClass, | |||
.SubClass = USB_CSCP_NoDeviceSubclass, | |||
.Protocol = USB_CSCP_NoDeviceProtocol, | |||
.Endpoint0Size = 8, | |||
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, | |||
/* specified in config.h */ | |||
.VendorID = VENDOR_ID, | |||
@@ -246,7 +246,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = | |||
.ProductStrIndex = 0x02, | |||
.SerialNumStrIndex = NO_DESCRIPTOR, | |||
.NumberOfConfigurations = 1 | |||
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS | |||
}; | |||
/******************************************************************************* | |||
@@ -292,7 +292,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = | |||
{ | |||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | |||
.HIDSpec = VERSION_BCD(01.11), | |||
.HIDSpec = VERSION_BCD(1,1,1), | |||
.CountryCode = 0x00, | |||
.TotalReportDescriptors = 1, | |||
.HIDReportType = HID_DTYPE_Report, | |||
@@ -306,7 +306,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = | |||
.EndpointAddress = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM), | |||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), | |||
.EndpointSize = KEYBOARD_EPSIZE, | |||
.PollingIntervalMS = 0x01 | |||
.PollingIntervalMS = 0x0A | |||
}, | |||
/* | |||
@@ -333,7 +333,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = | |||
{ | |||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | |||
.HIDSpec = VERSION_BCD(01.11), | |||
.HIDSpec = VERSION_BCD(1,1,1), | |||
.CountryCode = 0x00, | |||
.TotalReportDescriptors = 1, | |||
.HIDReportType = HID_DTYPE_Report, | |||
@@ -347,7 +347,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = | |||
.EndpointAddress = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM), | |||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), | |||
.EndpointSize = MOUSE_EPSIZE, | |||
.PollingIntervalMS = 0x01 | |||
.PollingIntervalMS = 0x0A | |||
}, | |||
#endif | |||
@@ -375,7 +375,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = | |||
{ | |||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | |||
.HIDSpec = VERSION_BCD(01.11), | |||
.HIDSpec = VERSION_BCD(1,1,1), | |||
.CountryCode = 0x00, | |||
.TotalReportDescriptors = 1, | |||
.HIDReportType = HID_DTYPE_Report, | |||
@@ -389,7 +389,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = | |||
.EndpointAddress = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM), | |||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), | |||
.EndpointSize = EXTRAKEY_EPSIZE, | |||
.PollingIntervalMS = 0x01 | |||
.PollingIntervalMS = 0x0A | |||
}, | |||
#endif | |||
@@ -417,7 +417,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = | |||
{ | |||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | |||
.HIDSpec = VERSION_BCD(01.11), | |||
.HIDSpec = VERSION_BCD(1,1,1), | |||
.CountryCode = 0x00, | |||
.TotalReportDescriptors = 1, | |||
.HIDReportType = HID_DTYPE_Report, | |||
@@ -469,7 +469,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = | |||
{ | |||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, | |||
.HIDSpec = VERSION_BCD(01.11), | |||
.HIDSpec = VERSION_BCD(1,1,1), | |||
.CountryCode = 0x00, | |||
.TotalReportDescriptors = 1, | |||
.HIDReportType = HID_DTYPE_Report, |
@@ -137,13 +137,17 @@ typedef struct | |||
#ifdef CONSOLE_ENABLE | |||
# define CONSOLE_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1) | |||
# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2) | |||
# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 1) | |||
//# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2) | |||
#else | |||
# define CONSOLE_OUT_EPNUM EXTRAKEY_IN_EPNUM | |||
#endif | |||
#ifdef NKRO_ENABLE | |||
# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1) | |||
# if defined(__AVR_ATmega32U2__) && NKRO_IN_EPNUM > 4 | |||
# error "Endpoints are not available enough to support all functions. Remove some in Makefile.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO)" | |||
# endif | |||
#endif | |||
@@ -159,4 +163,14 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, | |||
const void** const DescriptorAddress) | |||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); | |||
/* new API */ | |||
#if LUFA_VERSION_INTEGER < 0x140302 | |||
#undef VERSION_BCD | |||
#define VERSION_BCD(Major, Minor, Revision) \ | |||
CPU_TO_LE16( ((Major & 0xFF) << 8) | \ | |||
((Minor & 0x0F) << 4) | \ | |||
(Revision & 0x0F) ) | |||
#endif | |||
#endif |
@@ -52,8 +52,8 @@ | |||
#include "descriptor.h" | |||
#include "lufa.h" | |||
static uint8_t idle_duration = 0; | |||
static uint8_t protocol_report = 1; | |||
uint8_t keyboard_idle = 0; | |||
uint8_t keyboard_protocol = 1; | |||
static uint8_t keyboard_led_stats = 0; | |||
static report_keyboard_t keyboard_report_sent; | |||
@@ -184,15 +184,6 @@ void EVENT_USB_Device_StartOfFrame(void) | |||
/** Event handler for the USB_ConfigurationChanged event. | |||
* This is fired when the host sets the current configuration of the USB device after enumeration. | |||
*/ | |||
#if LUFA_VERSION_INTEGER < 0x120730 | |||
/* old API 120219 */ | |||
#define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint(epnum, eptype, epdir, epsize, epbank) | |||
#else | |||
/* new API >= 120730 */ | |||
#define ENDPOINT_BANK_SINGLE 1 | |||
#define ENDPOINT_BANK_DOUBLE 2 | |||
#define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint((epdir) | (epnum) , eptype, epsize, epbank) | |||
#endif | |||
void EVENT_USB_Device_ConfigurationChanged(void) | |||
{ | |||
bool ConfigSuccess = true; | |||
@@ -217,9 +208,11 @@ void EVENT_USB_Device_ConfigurationChanged(void) | |||
/* Setup Console HID Report Endpoints */ | |||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | |||
CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE); | |||
#if 0 | |||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, | |||
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); | |||
#endif | |||
#endif | |||
#ifdef NKRO_ENABLE | |||
/* Setup NKRO HID Report Endpoints */ | |||
@@ -279,6 +272,7 @@ void EVENT_USB_Device_ControlRequest(void) | |||
// Interface | |||
switch (USB_ControlRequest.wIndex) { | |||
case KEYBOARD_INTERFACE: | |||
case NKRO_INTERFACE: | |||
Endpoint_ClearSETUP(); | |||
while (!(Endpoint_IsOUTReceived())) { | |||
@@ -299,21 +293,29 @@ void EVENT_USB_Device_ControlRequest(void) | |||
case HID_REQ_GetProtocol: | |||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | |||
{ | |||
Endpoint_ClearSETUP(); | |||
while (!(Endpoint_IsINReady())); | |||
Endpoint_Write_8(protocol_report); | |||
Endpoint_ClearIN(); | |||
Endpoint_ClearStatusStage(); | |||
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) { | |||
Endpoint_ClearSETUP(); | |||
while (!(Endpoint_IsINReady())); | |||
Endpoint_Write_8(keyboard_protocol); | |||
Endpoint_ClearIN(); | |||
Endpoint_ClearStatusStage(); | |||
} | |||
} | |||
break; | |||
case HID_REQ_SetProtocol: | |||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | |||
{ | |||
Endpoint_ClearSETUP(); | |||
Endpoint_ClearStatusStage(); | |||
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) { | |||
Endpoint_ClearSETUP(); | |||
Endpoint_ClearStatusStage(); | |||
protocol_report = ((USB_ControlRequest.wValue & 0xFF) != 0x00); | |||
keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00); | |||
#ifdef NKRO_ENABLE | |||
keyboard_nkro = !!keyboard_protocol; | |||
#endif | |||
clear_keyboard(); | |||
} | |||
} | |||
break; | |||
@@ -323,7 +325,7 @@ void EVENT_USB_Device_ControlRequest(void) | |||
Endpoint_ClearSETUP(); | |||
Endpoint_ClearStatusStage(); | |||
idle_duration = ((USB_ControlRequest.wValue & 0xFF00) >> 8); | |||
keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8); | |||
} | |||
break; | |||
@@ -332,7 +334,7 @@ void EVENT_USB_Device_ControlRequest(void) | |||
{ | |||
Endpoint_ClearSETUP(); | |||
while (!(Endpoint_IsINReady())); | |||
Endpoint_Write_8(idle_duration); | |||
Endpoint_Write_8(keyboard_idle); | |||
Endpoint_ClearIN(); | |||
Endpoint_ClearStatusStage(); | |||
} | |||
@@ -351,7 +353,7 @@ static uint8_t keyboard_leds(void) | |||
static void send_keyboard(report_keyboard_t *report) | |||
{ | |||
uint8_t timeout = 0; | |||
uint8_t timeout = 255; | |||
if (USB_DeviceState != DEVICE_STATE_Configured) | |||
return; | |||
@@ -359,26 +361,27 @@ static void send_keyboard(report_keyboard_t *report) | |||
/* Select the Keyboard Report Endpoint */ | |||
#ifdef NKRO_ENABLE | |||
if (keyboard_nkro) { | |||
/* Report protocol - NKRO */ | |||
Endpoint_SelectEndpoint(NKRO_IN_EPNUM); | |||
} | |||
else | |||
#endif | |||
{ | |||
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); | |||
} | |||
/* Check if Keyboard Endpoint Ready for Read/Write */ | |||
while (--timeout && !Endpoint_IsReadWriteAllowed()) ; | |||
/* Check if write ready for a polling interval around 1ms */ | |||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4); | |||
if (!Endpoint_IsReadWriteAllowed()) return; | |||
/* Write Keyboard Report Data */ | |||
#ifdef NKRO_ENABLE | |||
if (keyboard_nkro) { | |||
/* Write Keyboard Report Data */ | |||
Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL); | |||
} | |||
else | |||
#endif | |||
{ | |||
/* boot mode */ | |||
/* Boot protocol */ | |||
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); | |||
/* Check if write ready for a polling interval around 10ms */ | |||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); | |||
if (!Endpoint_IsReadWriteAllowed()) return; | |||
/* Write Keyboard Report Data */ | |||
Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL); | |||
} | |||
@@ -391,7 +394,7 @@ static void send_keyboard(report_keyboard_t *report) | |||
static void send_mouse(report_mouse_t *report) | |||
{ | |||
#ifdef MOUSE_ENABLE | |||
uint8_t timeout = 0; | |||
uint8_t timeout = 255; | |||
if (USB_DeviceState != DEVICE_STATE_Configured) | |||
return; | |||
@@ -399,8 +402,9 @@ static void send_mouse(report_mouse_t *report) | |||
/* Select the Mouse Report Endpoint */ | |||
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM); | |||
/* Check if Mouse Endpoint Ready for Read/Write */ | |||
while (--timeout && !Endpoint_IsReadWriteAllowed()) ; | |||
/* Check if write ready for a polling interval around 10ms */ | |||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); | |||
if (!Endpoint_IsReadWriteAllowed()) return; | |||
/* Write Mouse Report Data */ | |||
Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL); | |||
@@ -412,7 +416,7 @@ static void send_mouse(report_mouse_t *report) | |||
static void send_system(uint16_t data) | |||
{ | |||
uint8_t timeout = 0; | |||
uint8_t timeout = 255; | |||
if (USB_DeviceState != DEVICE_STATE_Configured) | |||
return; | |||
@@ -422,14 +426,18 @@ static void send_system(uint16_t data) | |||
.usage = data | |||
}; | |||
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); | |||
while (--timeout && !Endpoint_IsReadWriteAllowed()) ; | |||
/* Check if write ready for a polling interval around 10ms */ | |||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); | |||
if (!Endpoint_IsReadWriteAllowed()) return; | |||
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); | |||
Endpoint_ClearIN(); | |||
} | |||
static void send_consumer(uint16_t data) | |||
{ | |||
uint8_t timeout = 0; | |||
uint8_t timeout = 255; | |||
if (USB_DeviceState != DEVICE_STATE_Configured) | |||
return; | |||
@@ -439,7 +447,11 @@ static void send_consumer(uint16_t data) | |||
.usage = data | |||
}; | |||
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); | |||
while (--timeout && !Endpoint_IsReadWriteAllowed()) ; | |||
/* Check if write ready for a polling interval around 10ms */ | |||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); | |||
if (!Endpoint_IsReadWriteAllowed()) return; | |||
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); | |||
Endpoint_ClearIN(); | |||
} |
@@ -66,4 +66,15 @@ typedef struct { | |||
uint16_t usage; | |||
} __attribute__ ((packed)) report_extra_t; | |||
#if LUFA_VERSION_INTEGER < 0x120730 | |||
/* old API 120219 */ | |||
#define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint(epnum, eptype, epdir, epsize, epbank) | |||
#else | |||
/* new API >= 120730 */ | |||
#define ENDPOINT_BANK_SINGLE 1 | |||
#define ENDPOINT_BANK_DOUBLE 2 | |||
#define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint((epdir) | (epnum) , eptype, epsize, epbank) | |||
#endif | |||
#endif |
@@ -38,6 +38,7 @@ | |||
#include "sleep_led.h" | |||
#endif | |||
#include "suspend.h" | |||
#include "action.h" | |||
#include "action_util.h" | |||
@@ -628,6 +629,7 @@ uint8_t usb_configured(void) | |||
void usb_remote_wakeup(void) | |||
{ | |||
UDCON |= (1<<RMWKUP); | |||
while (UDCON & (1<<RMWKUP)); | |||
} | |||
@@ -692,20 +694,20 @@ ISR(USB_GEN_vect) | |||
} | |||
/* TODO: should keep IDLE rate on each keyboard interface */ | |||
#ifdef NKRO_ENABLE | |||
if (!keyboard_nkro && usb_keyboard_idle_config && (++div4 & 3) == 0) { | |||
if (!keyboard_nkro && keyboard_idle && (++div4 & 3) == 0) { | |||
#else | |||
if (usb_keyboard_idle_config && (++div4 & 3) == 0) { | |||
if (keyboard_idle && (++div4 & 3) == 0) { | |||
#endif | |||
UENUM = KBD_ENDPOINT; | |||
if (UEINTX & (1<<RWAL)) { | |||
usb_keyboard_idle_count++; | |||
if (usb_keyboard_idle_count == usb_keyboard_idle_config) { | |||
if (usb_keyboard_idle_count == keyboard_idle) { | |||
usb_keyboard_idle_count = 0; | |||
/* TODO: fix keyboard_report inconsistency */ | |||
/* To avoid Mac SET_IDLE behaviour. | |||
UEDATX = keyboard_report_prev->mods; | |||
UEDATX = 0; | |||
uint8_t keys = usb_keyboard_protocol ? KBD_REPORT_KEYS : 6; | |||
uint8_t keys = keyboard_protocol ? KBD_REPORT_KEYS : 6; | |||
for (uint8_t i=0; i<keys; i++) { | |||
UEDATX = keyboard_report_prev->keys[i]; | |||
} | |||
@@ -901,13 +903,13 @@ ISR(USB_COM_vect) | |||
} | |||
if (bRequest == HID_GET_IDLE) { | |||
usb_wait_in_ready(); | |||
UEDATX = usb_keyboard_idle_config; | |||
UEDATX = keyboard_idle; | |||
usb_send_in(); | |||
return; | |||
} | |||
if (bRequest == HID_GET_PROTOCOL) { | |||
usb_wait_in_ready(); | |||
UEDATX = usb_keyboard_protocol; | |||
UEDATX = keyboard_protocol; | |||
usb_send_in(); | |||
return; | |||
} | |||
@@ -921,14 +923,18 @@ ISR(USB_COM_vect) | |||
return; | |||
} | |||
if (bRequest == HID_SET_IDLE) { | |||
usb_keyboard_idle_config = (wValue >> 8); | |||
keyboard_idle = (wValue >> 8); | |||
usb_keyboard_idle_count = 0; | |||
//usb_wait_in_ready(); | |||
usb_send_in(); | |||
return; | |||
} | |||
if (bRequest == HID_SET_PROTOCOL) { | |||
usb_keyboard_protocol = wValue; | |||
keyboard_protocol = wValue; | |||
#ifdef NKRO_ENABLE | |||
keyboard_nkro = !!keyboard_protocol; | |||
#endif | |||
clear_keyboard(); | |||
//usb_wait_in_ready(); | |||
usb_send_in(); | |||
return; |
@@ -34,12 +34,12 @@ | |||
// protocol setting from the host. We use exactly the same report | |||
// either way, so this variable only stores the setting since we | |||
// are required to be able to report which setting is in use. | |||
uint8_t usb_keyboard_protocol=1; | |||
uint8_t keyboard_protocol=1; | |||
// the idle configuration, how often we send the report to the | |||
// host (ms * 4) even when it hasn't changed | |||
// Windows and Linux set 0 while OS X sets 6(24ms) by SET_IDLE request. | |||
uint8_t usb_keyboard_idle_config=125; | |||
uint8_t keyobard_idle=125; | |||
// count until idle timeout | |||
uint8_t usb_keyboard_idle_count=0; | |||
@@ -61,10 +61,7 @@ int8_t usb_keyboard_send_report(report_keyboard_t *report) | |||
else | |||
#endif | |||
{ | |||
if (usb_keyboard_protocol) | |||
result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE); | |||
else | |||
result = send_report(report, KBD_ENDPOINT, 0, 6); | |||
result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE); | |||
} | |||
if (result) return result; |
@@ -30,8 +30,6 @@ | |||
#include "host.h" | |||
extern uint8_t usb_keyboard_protocol; | |||
extern uint8_t usb_keyboard_idle_config; | |||
extern uint8_t usb_keyboard_idle_count; | |||
extern volatile uint8_t usb_keyboard_leds; | |||
@@ -90,6 +90,7 @@ uint8_t ps2_host_send(uint8_t data); | |||
uint8_t ps2_host_recv_response(void); | |||
uint8_t ps2_host_recv(void); | |||
void ps2_host_set_led(uint8_t usb_led); | |||
uint8_t ps2_enabled(void); | |||
/* Check port settings for clock and data line */ |