@@ -29,7 +29,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
static void matrix_make(uint8_t code); | |||
static void matrix_break(uint8_t code); | |||
static void matrix_clear(void); | |||
/* | |||
@@ -155,8 +154,7 @@ static void matrix_break(uint8_t code) | |||
matrix[ROW(code)] &= ~(1<<COL(code)); | |||
} | |||
inline | |||
static void matrix_clear(void) | |||
void matrix_clear(void) | |||
{ | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||
} |
@@ -85,7 +85,7 @@ 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 | |||
#NKRO_ENABLE ?= yes # USB Nkey Rollover | |||
#KEYMAP_SECTION_ENABLE ?= yes # fixed address keymap for keymap editor | |||
@@ -68,9 +68,12 @@ ARCH ?= AVR8 | |||
# 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) | |||
# Interrupt driven control endpoint task | |||
# Not work with suart debug | |||
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
# This improves response of keyboard when wakeup | |||
OPT_DEFS += -DSUSPEND_MODE_STANDBY | |||
# Boot Section Size in *bytes* | |||
# Teensy halfKay 512 | |||
@@ -90,7 +93,7 @@ MOUSEKEY_ENABLE ?= no # 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 | |||
NKRO_ENABLE ?= yes # USB Nkey Rollover | |||
# PS/2 Options |
@@ -1,5 +1,6 @@ | |||
TARGET = ps2_usb_rev2_unimap | |||
UNIMAP_ENABLE = yes | |||
KEYMAP_SECTION_ENABLE = yes | |||
#LUFA_DEBUG_SUART = yes | |||
include Makefile.rev2 |
@@ -82,4 +82,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#define PS2_INT_VECT INT1_vect | |||
#endif | |||
#ifdef LUFA_DEBUG_SUART | |||
# define SUART_OUT_DDR DDRD | |||
# define SUART_OUT_PORT PORTD | |||
# define SUART_OUT_BIT 4 | |||
# define SUART_IN_DDR DDRD | |||
# define SUART_IN_PIN PIND | |||
# define SUART_IN_BIT 4 | |||
#endif | |||
#endif |
@@ -22,15 +22,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "util.h" | |||
#include "debug.h" | |||
#include "ps2.h" | |||
#include "host.h" | |||
#include "led.h" | |||
#include "matrix.h" | |||
static void matrix_make(uint8_t code); | |||
static void matrix_break(uint8_t code); | |||
static void matrix_clear(void); | |||
#ifdef MATRIX_HAS_GHOST | |||
static bool matrix_has_ghost_in_row(uint8_t row); | |||
#endif | |||
/* | |||
@@ -69,18 +67,6 @@ static uint8_t matrix[MATRIX_ROWS]; | |||
static bool is_modified = false; | |||
inline | |||
uint8_t matrix_rows(void) | |||
{ | |||
return MATRIX_ROWS; | |||
} | |||
inline | |||
uint8_t matrix_cols(void) | |||
{ | |||
return MATRIX_COLS; | |||
} | |||
void matrix_init(void) | |||
{ | |||
debug_enable = true; | |||
@@ -215,6 +201,12 @@ uint8_t matrix_scan(void) | |||
print("Overrun\n"); | |||
state = INIT; | |||
break; | |||
case 0xAA: // Self-test passed | |||
case 0xFC: // Self-test failed | |||
printf("BAT %s\n", (code == 0xAA) ? "OK" : "NG"); | |||
led_set(host_keyboard_leds()); | |||
state = INIT; | |||
break; | |||
default: // normal key make | |||
if (code < 0x80) { | |||
matrix_make(code); | |||
@@ -390,23 +382,6 @@ uint8_t matrix_scan(void) | |||
return 1; | |||
} | |||
bool matrix_is_modified(void) | |||
{ | |||
return is_modified; | |||
} | |||
inline | |||
bool matrix_has_ghost(void) | |||
{ | |||
#ifdef MATRIX_HAS_GHOST | |||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||
if (matrix_has_ghost_in_row(i)) | |||
return true; | |||
} | |||
#endif | |||
return false; | |||
} | |||
inline | |||
bool matrix_is_on(uint8_t row, uint8_t col) | |||
{ | |||
@@ -419,21 +394,6 @@ uint8_t matrix_get_row(uint8_t row) | |||
return matrix[row]; | |||
} | |||
void matrix_print(void) | |||
{ | |||
print("\nr/c 01234567\n"); | |||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||
phex(row); print(": "); | |||
pbin_reverse(matrix_get_row(row)); | |||
#ifdef MATRIX_HAS_GHOST | |||
if (matrix_has_ghost_in_row(row)) { | |||
print(" <ghost"); | |||
} | |||
#endif | |||
print("\n"); | |||
} | |||
} | |||
uint8_t matrix_key_count(void) | |||
{ | |||
uint8_t count = 0; | |||
@@ -443,23 +403,6 @@ uint8_t matrix_key_count(void) | |||
return count; | |||
} | |||
#ifdef MATRIX_HAS_GHOST | |||
inline | |||
static bool matrix_has_ghost_in_row(uint8_t row) | |||
{ | |||
// no ghost exists in case less than 2 keys on | |||
if (((matrix[row] - 1) & matrix[row]) == 0) | |||
return false; | |||
// ghost exists in case same state as other row | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||
if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | |||
return true; | |||
} | |||
return false; | |||
} | |||
#endif | |||
inline | |||
static void matrix_make(uint8_t code) | |||
@@ -479,8 +422,7 @@ static void matrix_break(uint8_t code) | |||
} | |||
} | |||
inline | |||
static void matrix_clear(void) | |||
void matrix_clear(void) | |||
{ | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||
} |
@@ -70,7 +70,7 @@ OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
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 | |||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||
# |
@@ -77,7 +77,7 @@ 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 | |||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||
@@ -81,7 +81,7 @@ 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 | |||
NKRO_ENABLE = yes # USB Nkey Rollover | |||
# XT/2 Options |
@@ -28,7 +28,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
static void matrix_make(uint8_t code); | |||
static void matrix_break(uint8_t code); | |||
static void matrix_clear(void); | |||
#ifdef MATRIX_HAS_GHOST | |||
static bool matrix_has_ghost_in_row(uint8_t row); | |||
#endif | |||
@@ -326,8 +325,7 @@ static void matrix_break(uint8_t code) | |||
} | |||
} | |||
inline | |||
static void matrix_clear(void) | |||
void matrix_clear(void) | |||
{ | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||
} |
@@ -112,7 +112,7 @@ 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 | |||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||
#ACTIONMAP_ENABLE = yes # Use 16bit action codes in keymap instead of 8bit keycodes | |||
@@ -119,7 +119,7 @@ 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 | |||
NKRO_ENABLE = yes # USB Nkey Rollover | |||
# Optimize size but this may cause error "relocation truncated to fit" |
@@ -114,7 +114,7 @@ OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||
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 | |||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||
#PS2_USE_BUSYWAIT = yes # uses primitive reference code |
@@ -26,12 +26,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "keymap.h" | |||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
{{KC_A}}, | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
static const action_t PROGMEM fn_actions[] = { | |||
const action_t PROGMEM fn_actions[] = { | |||
}; |
@@ -1,6 +1,7 @@ | |||
COMMON_DIR = common | |||
SRC += $(COMMON_DIR)/host.c \ | |||
$(COMMON_DIR)/keyboard.c \ | |||
$(COMMON_DIR)/matrix.c \ | |||
$(COMMON_DIR)/action.c \ | |||
$(COMMON_DIR)/action_tapping.c \ | |||
$(COMMON_DIR)/action_macro.c \ |
@@ -0,0 +1,156 @@ | |||
;---------------------------------------------------------------------------; | |||
; Software implemented UART module ; | |||
; (C)ChaN, 2005 (http://elm-chan.org/) ; | |||
;---------------------------------------------------------------------------; | |||
; Bit rate settings: | |||
; | |||
; 1MHz 2MHz 4MHz 6MHz 8MHz 10MHz 12MHz 16MHz 20MHz | |||
; 2.4kbps 138 - - - - - - - - | |||
; 4.8kbps 68 138 - - - - - - - | |||
; 9.6kbps 33 68 138 208 - - - - - | |||
; 19.2kbps - 33 68 102 138 173 208 - - | |||
; 38.4kbps - - 33 50 68 85 102 138 172 | |||
; 57.6kbps - - 21 33 44 56 68 91 114 | |||
; 115.2kbps - - - - 21 27 33 44 56 | |||
.nolist | |||
#include <avr/io.h> | |||
.list | |||
#define BPS 44 /* Bit delay. (see above table) */ | |||
#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */ | |||
#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */ | |||
#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */ | |||
#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */ | |||
#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */ | |||
#ifdef SPM_PAGESIZE | |||
.macro _LPMI reg | |||
lpm \reg, Z+ | |||
.endm | |||
.macro _MOVW dh,dl, sh,sl | |||
movw \dl, \sl | |||
.endm | |||
#else | |||
.macro _LPMI reg | |||
lpm | |||
mov \reg, r0 | |||
adiw ZL, 1 | |||
.endm | |||
.macro _MOVW dh,dl, sh,sl | |||
mov \dl, \sl | |||
mov \dh, \sh | |||
.endm | |||
#endif | |||
;---------------------------------------------------------------------------; | |||
; Transmit a byte in serial format of N81 | |||
; | |||
;Prototype: void xmit (uint8_t data); | |||
;Size: 16 words | |||
.global xmit | |||
.func xmit | |||
xmit: | |||
#if BIDIR | |||
ldi r23, BPS-1 ;Pre-idle time for bidirectional data line | |||
5: dec r23 ; | |||
brne 5b ;/ | |||
#endif | |||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||
com r24 ;C = start bit | |||
ldi r25, 10 ;Bit counter | |||
cli ;Start critical section | |||
1: ldi r23, BPS-1 ;----- Bit transferring loop | |||
2: dec r23 ;Wait for a bit time | |||
brne 2b ;/ | |||
brcs 3f ;MISO = bit to be sent | |||
OUT_1 ; | |||
3: brcc 4f ; | |||
OUT_0 ;/ | |||
4: lsr r24 ;Get next bit into C | |||
dec r25 ;All bits sent? | |||
brne 1b ; no, coutinue | |||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||
ret | |||
.endfunc | |||
;---------------------------------------------------------------------------; | |||
; Receive a byte | |||
; | |||
;Prototype: uint8_t rcvr (void); | |||
;Size: 19 words | |||
.global rcvr | |||
.func rcvr | |||
rcvr: | |||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||
ldi r24, 0x80 ;Receiving shift reg | |||
cli ;Start critical section | |||
1: SKIP_IN_1 ;Wait for idle | |||
rjmp 1b | |||
2: SKIP_IN_0 ;Wait for start bit | |||
rjmp 2b | |||
ldi r25, BPS/2 ;Wait for half bit time | |||
3: dec r25 | |||
brne 3b | |||
4: ldi r25, BPS ;----- Bit receiving loop | |||
5: dec r25 ;Wait for a bit time | |||
brne 5b ;/ | |||
lsr r24 ;Next bit | |||
SKIP_IN_0 ;Get a data bit into r24.7 | |||
ori r24, 0x80 | |||
brcc 4b ;All bits received? no, continue | |||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||
ret | |||
.endfunc | |||
; Not wait for start bit. This should be called after detecting start bit. | |||
.global recv | |||
.func recv | |||
recv: | |||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||
ldi r24, 0x80 ;Receiving shift reg | |||
cli ;Start critical section | |||
;1: SKIP_IN_1 ;Wait for idle | |||
; rjmp 1b | |||
;2: SKIP_IN_0 ;Wait for start bit | |||
; rjmp 2b | |||
ldi r25, BPS/2 ;Wait for half bit time | |||
3: dec r25 | |||
brne 3b | |||
4: ldi r25, BPS ;----- Bit receiving loop | |||
5: dec r25 ;Wait for a bit time | |||
brne 5b ;/ | |||
lsr r24 ;Next bit | |||
SKIP_IN_0 ;Get a data bit into r24.7 | |||
ori r24, 0x80 | |||
brcc 4b ;All bits received? no, continue | |||
ldi r25, BPS/2 ;Wait for half bit time | |||
6: dec r25 | |||
brne 6b | |||
7: SKIP_IN_1 ;Wait for stop bit | |||
rjmp 7b | |||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||
ret | |||
.endfunc |
@@ -0,0 +1,8 @@ | |||
#ifndef SUART | |||
#define SUART | |||
void xmit(uint8_t); | |||
uint8_t rcvr(void); | |||
uint8_t recv(void); | |||
#endif /* SUART */ |
@@ -30,16 +30,6 @@ __asm__ __volatile__ ( \ | |||
) | |||
void suspend_idle(uint8_t time) | |||
{ | |||
cli(); | |||
set_sleep_mode(SLEEP_MODE_IDLE); | |||
sleep_enable(); | |||
sei(); | |||
sleep_cpu(); | |||
sleep_disable(); | |||
} | |||
/* Power down MCU with watchdog timer | |||
* wdto: watchdog timer timeout defined in <avr/wdt.h> | |||
* WDTO_15MS | |||
@@ -80,13 +70,41 @@ static void power_down(uint8_t wdto) | |||
wdt_disable(); | |||
} | |||
static void standby(void) | |||
{ | |||
set_sleep_mode(SLEEP_MODE_STANDBY); | |||
sleep_enable(); | |||
sei(); | |||
sleep_cpu(); | |||
sleep_disable(); | |||
} | |||
static void idle(void) | |||
{ | |||
set_sleep_mode(SLEEP_MODE_IDLE); | |||
sleep_enable(); | |||
sei(); | |||
sleep_cpu(); | |||
sleep_disable(); | |||
} | |||
void suspend_idle(uint8_t time) | |||
{ | |||
idle(); | |||
} | |||
void suspend_power_down(void) | |||
{ | |||
#ifdef SUSPEND_MODE_STANDBY | |||
standby(); | |||
#elif defined(SUSPEND_MODE_IDLE) | |||
idle(); | |||
#else | |||
power_down(WDTO_15MS); | |||
#endif | |||
} | |||
__attribute__ ((weak)) void matrix_power_up(void) {} | |||
__attribute__ ((weak)) void matrix_power_down(void) {} | |||
bool suspend_wakeup_condition(void) | |||
{ | |||
matrix_power_up(); | |||
@@ -102,6 +120,7 @@ bool suspend_wakeup_condition(void) | |||
void suspend_wakeup_init(void) | |||
{ | |||
// clear keyboard state | |||
matrix_clear(); | |||
clear_keyboard(); | |||
#ifdef BACKLIGHT_ENABLE | |||
backlight_init(); |
@@ -66,7 +66,6 @@ static bool has_ghost_in_row(uint8_t row) | |||
#endif | |||
__attribute__ ((weak)) void matrix_setup(void) {} | |||
void keyboard_setup(void) | |||
{ | |||
matrix_setup(); |
@@ -0,0 +1,97 @@ | |||
/* | |||
Copyright 2016 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 "print.h" | |||
#include "matrix.h" | |||
__attribute__ ((weak)) | |||
uint8_t matrix_rows(void) | |||
{ | |||
return MATRIX_ROWS; | |||
} | |||
__attribute__ ((weak)) | |||
uint8_t matrix_cols(void) | |||
{ | |||
return MATRIX_COLS; | |||
} | |||
__attribute__ ((weak)) | |||
void matrix_clear(void) | |||
{ | |||
matrix_init(); | |||
} | |||
__attribute__ ((weak)) | |||
void matrix_setup(void) {} | |||
__attribute__ ((weak)) | |||
bool matrix_is_on(uint8_t row, uint8_t col) | |||
{ | |||
return (matrix_get_row(row) & (1<<col)); | |||
} | |||
__attribute__ ((weak)) | |||
void matrix_print(void) | |||
{ | |||
#if (MATRIX_COLS <= 8) | |||
print("r/c 01234567\n"); | |||
#elif (MATRIX_COLS <= 16) | |||
print("r/c 0123456789ABCDEF\n"); | |||
#elif (MATRIX_COLS <= 32) | |||
print("r/c 0123456789ABCDEF0123456789ABCDEF\n"); | |||
#endif | |||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | |||
xprintf("%02X:", row); | |||
#if (MATRIX_COLS <= 8) | |||
print_bin_reverse8(matrix_get_row(row)); | |||
#elif (MATRIX_COLS <= 16) | |||
print_bin_reverse16(matrix_get_row(row)); | |||
#elif (MATRIX_COLS <= 32) | |||
print_bin_reverse32(matrix_get_row(row)); | |||
#endif | |||
#ifdef MATRIX_HAS_GHOST | |||
if (matrix_has_ghost_in_row(row)) { | |||
print(" <ghost"); | |||
} | |||
#endif | |||
print("\n"); | |||
} | |||
} | |||
#ifdef MATRIX_HAS_GHOST | |||
__attribute__ ((weak)) | |||
bool matrix_has_ghost_in_row(uint8_t row) | |||
{ | |||
matrix_row_t matrix_row = matrix_get_row(row); | |||
// No ghost exists when less than 2 keys are down on the row | |||
if (((matrix_row - 1) & matrix_row) == 0) | |||
return false; | |||
// Ghost occurs when the row shares column line with other row | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||
if (i != row && (matrix_get_row(i) & matrix_row)) | |||
return true; | |||
} | |||
return false; | |||
} | |||
#endif | |||
__attribute__ ((weak)) void matrix_power_up(void) {} | |||
__attribute__ ((weak)) void matrix_power_down(void) {} |
@@ -57,7 +57,12 @@ bool matrix_is_on(uint8_t row, uint8_t col); | |||
matrix_row_t matrix_get_row(uint8_t row); | |||
/* print matrix for debug */ | |||
void matrix_print(void); | |||
/* clear matrix */ | |||
void matrix_clear(void); | |||
#ifdef MATRIX_HAS_GHOST | |||
bool matrix_has_ghost_in_row(uint8_t row); | |||
#endif | |||
/* power control */ | |||
void matrix_power_up(void); |
@@ -48,3 +48,8 @@ OPT_DEFS += $(LUFA_OPTS) | |||
# This indicates using LUFA stack | |||
OPT_DEFS += -DPROTOCOL_LUFA | |||
ifeq (yes,$(strip $(LUFA_DEBUG_SUART))) | |||
SRC += common/avr/suart.S | |||
LUFA_OPTS += -DLUFA_DEBUG_SUART | |||
endif |
@@ -1,4 +1,4 @@ | |||
/* | |||
/* | |||
* Copyright 2012 Jun Wako <[email protected]> | |||
* This file is based on: | |||
* LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse | |||
@@ -50,9 +50,18 @@ | |||
#include "suspend.h" | |||
#include "hook.h" | |||
#ifdef LUFA_DEBUG_SUART | |||
#include "avr/suart.h" | |||
#endif | |||
#include "matrix.h" | |||
#include "descriptor.h" | |||
#include "lufa.h" | |||
//#define LUFA_DEBUG | |||
uint8_t keyboard_idle = 0; | |||
/* 0: Boot Protocol, 1: Report Protocol(default) */ | |||
uint8_t keyboard_protocol = 1; | |||
@@ -100,10 +109,10 @@ static void Console_Task(void) | |||
{ | |||
/* Create a temporary buffer to hold the read in report from the host */ | |||
uint8_t ConsoleData[CONSOLE_EPSIZE]; | |||
/* Read Console Report Data */ | |||
Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL); | |||
/* Process Console Report Data */ | |||
//ProcessConsoleHIDReport(ConsoleData); | |||
} | |||
@@ -164,7 +173,7 @@ void EVENT_USB_Device_Disconnect(void) | |||
print("[D]"); | |||
/* For battery powered device */ | |||
USB_IsInitialized = false; | |||
/* TODO: This doesn't work. After several plug in/outs can not be enumerated. | |||
/* TODO: This doesn't work. After several plug in/outs can not be enumerated. | |||
if (USB_IsInitialized) { | |||
USB_Disable(); // Disable all interrupts | |||
USB_Controller_Enable(); | |||
@@ -175,18 +184,24 @@ void EVENT_USB_Device_Disconnect(void) | |||
void EVENT_USB_Device_Reset(void) | |||
{ | |||
#ifdef LUFA_DEBUG | |||
print("[R]"); | |||
#endif | |||
} | |||
void EVENT_USB_Device_Suspend() | |||
{ | |||
#ifdef LUFA_DEBUG | |||
print("[S]"); | |||
#endif | |||
hook_usb_suspend_entry(); | |||
} | |||
void EVENT_USB_Device_WakeUp() | |||
{ | |||
#ifdef LUFA_DEBUG | |||
print("[W]"); | |||
#endif | |||
hook_usb_wakeup(); | |||
} | |||
@@ -217,6 +232,9 @@ void EVENT_USB_Device_StartOfFrame(void) | |||
*/ | |||
void EVENT_USB_Device_ConfigurationChanged(void) | |||
{ | |||
#ifdef LUFA_DEBUG | |||
print("[c]"); | |||
#endif | |||
bool ConfigSuccess = true; | |||
/* Setup Keyboard HID Report Endpoints */ | |||
@@ -293,6 +311,9 @@ void EVENT_USB_Device_ControlRequest(void) | |||
/* Write the report data to the control endpoint */ | |||
Endpoint_Write_Control_Stream_LE(ReportData, ReportSize); | |||
Endpoint_ClearOUT(); | |||
#ifdef LUFA_DEBUG | |||
xprintf("[r%d]", USB_ControlRequest.wIndex); | |||
#endif | |||
} | |||
break; | |||
@@ -316,6 +337,9 @@ void EVENT_USB_Device_ControlRequest(void) | |||
Endpoint_ClearOUT(); | |||
Endpoint_ClearStatusStage(); | |||
#ifdef LUFA_DEBUG | |||
xprintf("[L%d]", USB_ControlRequest.wIndex); | |||
#endif | |||
break; | |||
} | |||
@@ -332,6 +356,9 @@ void EVENT_USB_Device_ControlRequest(void) | |||
Endpoint_Write_8(keyboard_protocol); | |||
Endpoint_ClearIN(); | |||
Endpoint_ClearStatusStage(); | |||
#ifdef LUFA_DEBUG | |||
print("[p]"); | |||
#endif | |||
} | |||
} | |||
@@ -345,6 +372,9 @@ void EVENT_USB_Device_ControlRequest(void) | |||
keyboard_protocol = (USB_ControlRequest.wValue & 0xFF); | |||
clear_keyboard(); | |||
#ifdef LUFA_DEBUG | |||
print("[P]"); | |||
#endif | |||
} | |||
} | |||
@@ -356,6 +386,9 @@ void EVENT_USB_Device_ControlRequest(void) | |||
Endpoint_ClearStatusStage(); | |||
keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8); | |||
#ifdef LUFA_DEBUG | |||
xprintf("[I%d]%d", USB_ControlRequest.wIndex, (USB_ControlRequest.wValue & 0xFF00) >> 8); | |||
#endif | |||
} | |||
break; | |||
@@ -367,6 +400,9 @@ void EVENT_USB_Device_ControlRequest(void) | |||
Endpoint_Write_8(keyboard_idle); | |||
Endpoint_ClearIN(); | |||
Endpoint_ClearStatusStage(); | |||
#ifdef LUFA_DEBUG | |||
print("[i]"); | |||
#endif | |||
} | |||
break; | |||
@@ -374,7 +410,7 @@ void EVENT_USB_Device_ControlRequest(void) | |||
} | |||
/******************************************************************************* | |||
* Host driver | |||
* Host driver | |||
******************************************************************************/ | |||
static uint8_t keyboard_leds(void) | |||
{ | |||
@@ -494,6 +530,9 @@ static void send_consumer(uint16_t data) | |||
#define SEND_TIMEOUT 5 | |||
int8_t sendchar(uint8_t c) | |||
{ | |||
#ifdef LUFA_DEBUG_SUART | |||
xmit(c); | |||
#endif | |||
// Not wait once timeouted. | |||
// Because sendchar() is called so many times, waiting each call causes big lag. | |||
static bool timeouted = false; | |||
@@ -551,6 +590,9 @@ ERROR_EXIT: | |||
#else | |||
int8_t sendchar(uint8_t c) | |||
{ | |||
#ifdef LUFA_DEBUG_SUART | |||
xmit(c); | |||
#endif | |||
return 0; | |||
} | |||
#endif | |||
@@ -578,13 +620,20 @@ static void setup_usb(void) | |||
// for Console_Task | |||
USB_Device_EnableSOFEvents(); | |||
print_set_sendchar(sendchar); | |||
} | |||
int main(void) __attribute__ ((weak)); | |||
int main(void) | |||
{ | |||
setup_mcu(); | |||
#ifdef LUFA_DEBUG_SUART | |||
SUART_OUT_DDR |= (1<<SUART_OUT_BIT); | |||
SUART_OUT_PORT |= (1<<SUART_OUT_BIT); | |||
#endif | |||
print_set_sendchar(sendchar); | |||
print("\r\ninit\n"); | |||
hook_early_init(); | |||
keyboard_setup(); | |||
setup_usb(); | |||
@@ -611,7 +660,9 @@ int main(void) | |||
hook_late_init(); | |||
while (1) { | |||
while (USB_DeviceState == DEVICE_STATE_Suspended) { | |||
#ifdef LUFA_DEBUG | |||
print("[s]"); | |||
#endif | |||
hook_usb_suspend_loop(); | |||
} | |||
@@ -631,9 +682,19 @@ void hook_early_init(void) {} | |||
__attribute__((weak)) | |||
void hook_late_init(void) {} | |||
static uint8_t _led_stats = 0; | |||
__attribute__((weak)) | |||
void hook_usb_suspend_entry(void) | |||
{ | |||
// Turn LED off to save power | |||
// Set 0 with putting aside status before suspend and restore | |||
// it after wakeup, then LED is updated at keyboard_task() in main loop | |||
_led_stats = keyboard_led_stats; | |||
keyboard_led_stats = 0; | |||
led_set(keyboard_led_stats); | |||
matrix_clear(); | |||
clear_keyboard(); | |||
#ifdef SLEEP_LED_ENABLE | |||
sleep_led_enable(); | |||
#endif | |||
@@ -644,7 +705,7 @@ void hook_usb_suspend_loop(void) | |||
{ | |||
suspend_power_down(); | |||
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { | |||
USB_Device_SendRemoteWakeup(); | |||
USB_Device_SendRemoteWakeup(); | |||
} | |||
} | |||
@@ -654,7 +715,12 @@ void hook_usb_wakeup(void) | |||
suspend_wakeup_init(); | |||
#ifdef SLEEP_LED_ENABLE | |||
sleep_led_disable(); | |||
// NOTE: converters may not accept this | |||
led_set(host_keyboard_leds()); | |||
#endif | |||
// Restore LED status | |||
// BIOS/grub won't recognize/enumerate if led_set() takes long(around 40ms?) | |||
// Converters fall into the case and miss wakeup event(timeout to reply?) in the end. | |||
//led_set(host_keyboard_leds()); | |||
// Instead, restore stats and update at keyboard_task() in main loop | |||
keyboard_led_stats = _led_stats; | |||
} |