Merge branch 'lufa_nkro'
This commit is contained in:
commit
893ff0a799
@ -37,8 +37,10 @@ static uint16_t last_consumer_report = 0;
|
|||||||
|
|
||||||
static inline void add_key_byte(uint8_t code);
|
static inline void add_key_byte(uint8_t code);
|
||||||
static inline void del_key_byte(uint8_t code);
|
static inline void del_key_byte(uint8_t code);
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
static inline void add_key_bit(uint8_t code);
|
static inline void add_key_bit(uint8_t code);
|
||||||
static inline void del_key_bit(uint8_t code);
|
static inline void del_key_bit(uint8_t code);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void host_set_driver(host_driver_t *d)
|
void host_set_driver(host_driver_t *d)
|
||||||
@ -63,11 +65,11 @@ void host_keyboard_send(report_keyboard_t *report)
|
|||||||
(*driver->send_keyboard)(report);
|
(*driver->send_keyboard)(report);
|
||||||
|
|
||||||
if (debug_keyboard) {
|
if (debug_keyboard) {
|
||||||
dprint("keys: ");
|
dprint("keyboard_report: ");
|
||||||
for (int i = 0; i < REPORT_KEYS; i++) {
|
for (uint8_t i = 0; i < REPORT_SIZE; i++) {
|
||||||
dprintf("%02X ", keyboard_report->keys[i]);
|
dprintf("%02X ", keyboard_report->raw[i]);
|
||||||
}
|
}
|
||||||
dprintf(" mods: %02X\n", keyboard_report->mods);
|
dprint("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,8 +124,9 @@ void host_del_key(uint8_t key)
|
|||||||
|
|
||||||
void host_clear_keys(void)
|
void host_clear_keys(void)
|
||||||
{
|
{
|
||||||
for (int8_t i = 0; i < REPORT_KEYS; i++) {
|
// not clea mods
|
||||||
keyboard_report->keys[i] = 0;
|
for (int8_t i = 1; i < REPORT_SIZE; i++) {
|
||||||
|
keyboard_report->raw[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,8 +158,8 @@ void host_clear_mods(void)
|
|||||||
uint8_t host_has_anykey(void)
|
uint8_t host_has_anykey(void)
|
||||||
{
|
{
|
||||||
uint8_t cnt = 0;
|
uint8_t cnt = 0;
|
||||||
for (int i = 0; i < REPORT_KEYS; i++) {
|
for (uint8_t i = 1; i < REPORT_SIZE; i++) {
|
||||||
if (keyboard_report->keys[i])
|
if (keyboard_report->raw[i])
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
@ -172,9 +175,9 @@ uint8_t host_get_first_key(void)
|
|||||||
#ifdef NKRO_ENABLE
|
#ifdef NKRO_ENABLE
|
||||||
if (keyboard_nkro) {
|
if (keyboard_nkro) {
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++)
|
for (; i < REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
|
||||||
;
|
;
|
||||||
return i<<3 | biton(keyboard_report->keys[i]);
|
return i<<3 | biton(keyboard_report->nkro.bits[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return keyboard_report->keys[0];
|
return keyboard_report->keys[0];
|
||||||
@ -222,18 +225,18 @@ static inline void add_key_byte(uint8_t code)
|
|||||||
|
|
||||||
static inline void del_key_byte(uint8_t code)
|
static inline void del_key_byte(uint8_t code)
|
||||||
{
|
{
|
||||||
int i = 0;
|
for (uint8_t i = 0; i < REPORT_KEYS; i++) {
|
||||||
for (; i < REPORT_KEYS; i++) {
|
|
||||||
if (keyboard_report->keys[i] == code) {
|
if (keyboard_report->keys[i] == code) {
|
||||||
keyboard_report->keys[i] = 0;
|
keyboard_report->keys[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
static inline void add_key_bit(uint8_t code)
|
static inline void add_key_bit(uint8_t code)
|
||||||
{
|
{
|
||||||
if ((code>>3) < REPORT_KEYS) {
|
if ((code>>3) < REPORT_BITS) {
|
||||||
keyboard_report->keys[code>>3] |= 1<<(code&7);
|
keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
|
||||||
} else {
|
} else {
|
||||||
dprintf("add_key_bit: can't add: %02X\n", code);
|
dprintf("add_key_bit: can't add: %02X\n", code);
|
||||||
}
|
}
|
||||||
@ -241,9 +244,10 @@ static inline void add_key_bit(uint8_t code)
|
|||||||
|
|
||||||
static inline void del_key_bit(uint8_t code)
|
static inline void del_key_bit(uint8_t code)
|
||||||
{
|
{
|
||||||
if ((code>>3) < REPORT_KEYS) {
|
if ((code>>3) < REPORT_BITS) {
|
||||||
keyboard_report->keys[code>>3] &= ~(1<<(code&7));
|
keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
|
||||||
} else {
|
} else {
|
||||||
dprintf("del_key_bit: can't del: %02X\n", code);
|
dprintf("del_key_bit: can't del: %02X\n", code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -72,14 +72,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
|
|
||||||
/* key report size(NKRO or boot mode) */
|
/* key report size(NKRO or boot mode) */
|
||||||
#if defined(PROTOCOL_PJRC)
|
#if defined(PROTOCOL_PJRC) && defined(NKRO_ENABLE)
|
||||||
# include "usb.h"
|
# include "usb.h"
|
||||||
# if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS
|
# define REPORT_SIZE KBD2_SIZE
|
||||||
# define REPORT_KEYS KBD2_REPORT_KEYS
|
# define REPORT_KEYS (KBD2_SIZE - 2)
|
||||||
# else
|
# define REPORT_BITS (KBD2_SIZE - 1)
|
||||||
# define REPORT_KEYS KBD_REPORT_KEYS
|
|
||||||
# endif
|
#elif defined(PROTOCOL_LUFA) && defined(NKRO_ENABLE)
|
||||||
|
# include "protocol/lufa/descriptor.h"
|
||||||
|
# define REPORT_SIZE NKRO_EPSIZE
|
||||||
|
# define REPORT_KEYS (NKRO_EPSIZE - 2)
|
||||||
|
# define REPORT_BITS (NKRO_EPSIZE - 1)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
# define REPORT_SIZE 8
|
||||||
# define REPORT_KEYS 6
|
# define REPORT_KEYS 6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -88,11 +94,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint8_t raw[REPORT_SIZE];
|
||||||
|
struct {
|
||||||
|
uint8_t mods;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint8_t keys[REPORT_KEYS];
|
||||||
|
};
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
struct {
|
||||||
|
uint8_t mods;
|
||||||
|
uint8_t bits[REPORT_BITS];
|
||||||
|
} nkro;
|
||||||
|
#endif
|
||||||
|
} __attribute__ ((packed)) report_keyboard_t;
|
||||||
|
/*
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t mods;
|
uint8_t mods;
|
||||||
uint8_t rserved;
|
uint8_t reserved;
|
||||||
uint8_t keys[REPORT_KEYS];
|
uint8_t keys[REPORT_KEYS];
|
||||||
} __attribute__ ((packed)) report_keyboard_t;
|
} __attribute__ ((packed)) report_keyboard_t;
|
||||||
|
*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t buttons;
|
uint8_t buttons;
|
||||||
|
@ -57,8 +57,10 @@ CONFIG_H = config.h
|
|||||||
|
|
||||||
|
|
||||||
# MCU name
|
# MCU name
|
||||||
MCU = at90usb1286
|
# PJRC Teensy++ 2.0
|
||||||
#MCU = atmega32u4
|
#MCU = at90usb1286
|
||||||
|
# TMK Alt Controller or PJRC Teensy 2.0
|
||||||
|
MCU = atmega32u4
|
||||||
|
|
||||||
# Processor frequency.
|
# Processor frequency.
|
||||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||||
@ -100,10 +102,10 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
|
|||||||
# Boot Section Size in *bytes*
|
# Boot Section Size in *bytes*
|
||||||
# Teensy halfKay 512
|
# Teensy halfKay 512
|
||||||
# Teensy++ halfKay 1024
|
# Teensy++ halfKay 1024
|
||||||
# Atmel DFU loader 4096
|
# Atmel DFU loader 4096 (TMK Alt Controller)
|
||||||
# LUFA bootloader 4096
|
# LUFA bootloader 4096
|
||||||
# USBaspLoader 2048
|
# USBaspLoader 2048
|
||||||
OPT_DEFS += -DBOOTLOADER_SIZE=512
|
OPT_DEFS += -DBOOTLOADER_SIZE=4096
|
||||||
|
|
||||||
|
|
||||||
# Build Options
|
# Build Options
|
||||||
@ -114,7 +116,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys
|
|||||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
EXTRAKEY_ENABLE = yes # Audio control and System control
|
||||||
CONSOLE_ENABLE = yes # Console for debug
|
CONSOLE_ENABLE = yes # Console for debug
|
||||||
COMMAND_ENABLE = yes # Commands for debug and configuration
|
COMMAND_ENABLE = yes # Commands for debug and configuration
|
||||||
#NKRO_ENABLE = yes # USB Nkey Rollover
|
NKRO_ENABLE = yes # USB Nkey Rollover
|
||||||
|
|
||||||
|
|
||||||
# Search Path
|
# Search Path
|
@ -23,9 +23,9 @@ CONFIG_H = config.h
|
|||||||
# MCU name, you MUST set this to match the board you are using
|
# 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
|
# type "make clean" after changing this, so all files will be rebuilt
|
||||||
#MCU = at90usb162 # Teensy 1.0
|
#MCU = at90usb162 # Teensy 1.0
|
||||||
#MCU = atmega32u4 # Teensy 2.0
|
MCU = atmega32u4 # Teensy 2.0
|
||||||
#MCU = at90usb646 # Teensy++ 1.0
|
#MCU = at90usb646 # Teensy++ 1.0
|
||||||
MCU = at90usb1286 # Teensy++ 2.0
|
#MCU = at90usb1286 # Teensy++ 2.0
|
||||||
|
|
||||||
|
|
||||||
# Processor frequency.
|
# Processor frequency.
|
||||||
|
@ -1,129 +0,0 @@
|
|||||||
#----------------------------------------------------------------------------
|
|
||||||
# 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 = hhkb_tmk
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
CONFIG_H = config.h
|
|
||||||
|
|
||||||
|
|
||||||
# MCU name
|
|
||||||
#MCU = at90usb1286
|
|
||||||
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
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
# Build Options
|
|
||||||
# comment out to disable the options.
|
|
||||||
#
|
|
||||||
#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
|
|
||||||
MOUSEKEY_ENABLE = yes # Mouse keys
|
|
||||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
|
||||||
CONSOLE_ENABLE = yes # Console for debug
|
|
||||||
COMMAND_ENABLE = yes # Commands for debug and configuration
|
|
||||||
#NKRO_ENABLE = yes # USB Nkey Rollover
|
|
||||||
|
|
||||||
|
|
||||||
# Search Path
|
|
||||||
VPATH += $(TARGET_DIR)
|
|
||||||
VPATH += $(TOP_DIR)
|
|
||||||
|
|
||||||
include $(TOP_DIR)/protocol/lufa.mk
|
|
||||||
include $(TOP_DIR)/common.mk
|
|
||||||
include $(TOP_DIR)/rules.mk
|
|
||||||
|
|
||||||
debug-on: EXTRAFLAGS += -DDEBUG
|
|
||||||
debug-on: all
|
|
@ -8,7 +8,6 @@ See [this thread][AltController] in geekhack.org.
|
|||||||
|
|
||||||
[HHKB]: http://www.pfu.fujitsu.com/hhkeyboard/
|
[HHKB]: http://www.pfu.fujitsu.com/hhkeyboard/
|
||||||
[AltController]: http://geekhack.org/index.php?topic=12047.0
|
[AltController]: http://geekhack.org/index.php?topic=12047.0
|
||||||
[Teensy]: http://www.pjrc.com/teensy/
|
|
||||||
|
|
||||||
|
|
||||||
##Features
|
##Features
|
||||||
@ -22,8 +21,8 @@ See README of [tmk_keyboard] for more.
|
|||||||
[tmk_keyboard]: http://github.com/tmk/tmk_keyboard
|
[tmk_keyboard]: http://github.com/tmk/tmk_keyboard
|
||||||
|
|
||||||
###Pros
|
###Pros
|
||||||
* No risk: Everything is all reversible
|
* No risks: Everything is all reversible
|
||||||
* Without PCB trace cutting, case mod or any destructives
|
* No need for PCB trace patching, case cutting or any other destructive mod
|
||||||
* Can keep original controller intact
|
* Can keep original controller intact
|
||||||
* Can change all HHKB behaviour as you like
|
* Can change all HHKB behaviour as you like
|
||||||
|
|
||||||
@ -41,61 +40,35 @@ See [doc/HHKB.txt](doc/HHKB.txt) and files under [doc/](doc/) for internal of HH
|
|||||||
|
|
||||||
|
|
||||||
##Build Firmware & Program
|
##Build Firmware & Program
|
||||||
You can choose some combination of hardware and USB protocol stack([LUFA], [PJRC]).
|
See [this document](../../doc/build.md) first.
|
||||||
|
|
||||||
### Install Tools
|
### Configuration
|
||||||
See [this document](../../doc/build.md).
|
Set `MCU`, `BOOTLOADER_SIZE` and other build options in `Makefile` and `config.h`.
|
||||||
|
|
||||||
### TMK Alt Controller Board
|
### Build
|
||||||
$ make -f Makefile.tmk
|
Just run make after intall tools.
|
||||||
|
|
||||||
This programs the controller with [dfu-programmer] if the tool is intalled and configured properly.
|
$ make
|
||||||
|
|
||||||
$ make -f Makefile.tmk dfu
|
Use `Makefile.pjrc` if you want to use PJRC stack instead of LUFA.(LUFA is recommended.)
|
||||||
|
|
||||||
Push reset button and program with [FLIP]. The tool should be intalled and configured properly.
|
|
||||||
|
|
||||||
$ make -f Makefile.tmk flip
|
|
||||||
|
|
||||||
Or you can also program with FLIP GUI.
|
|
||||||
|
|
||||||
[dfu-programmer]: http://dfu-programmer.sourceforge.net/
|
|
||||||
[FLIP]: http://www.atmel.com/tools/FLIP.aspx
|
|
||||||
|
|
||||||
|
|
||||||
### PJRC Teensy++
|
|
||||||
Build with [LUFA] USB stack:
|
|
||||||
|
|
||||||
$ make -f Makefile.lufa
|
|
||||||
|
|
||||||
or with [PJRC] USB stack:
|
|
||||||
|
|
||||||
$ make -f Makefile.pjrc
|
$ make -f Makefile.pjrc
|
||||||
|
|
||||||
Push reset button and program with [Teensy Loader(command line)]. The tool should be intalled and configured properly.
|
Use `Makefile.vusb` for [V-USB] controller.(not supported actively any more.)
|
||||||
|
|
||||||
$ make -f Makefile.lufa teensy
|
|
||||||
$ make -f Makefile.pjrc teensy
|
|
||||||
|
|
||||||
Or you can also program with [Teensy Loader(GUI)].
|
|
||||||
|
|
||||||
[LUFA]: http://www.fourwalledcubicle.com/LUFA.php
|
|
||||||
[PJRC]: http://www.pjrc.com/teensy/usb_keyboard.html
|
|
||||||
[Teensy Loader(command line)]: http://www.pjrc.com/teensy/loader_cli.html
|
|
||||||
[Teensy Loader(GUI)]: http://www.pjrc.com/teensy/loader.html
|
|
||||||
|
|
||||||
|
|
||||||
###AVR Mega with [V-USB]
|
|
||||||
Build:
|
|
||||||
$ make -f Makefile.vusb
|
$ make -f Makefile.vusb
|
||||||
|
|
||||||
Program [USBaspLoader] on MCU with AVR programmer like [AVRISPmkII] and tool like [avrdude].
|
### Program
|
||||||
|
First, push reset button on board to start bootloader.
|
||||||
|
|
||||||
You can programs with [avrdude] once you have programmed [USBaspLoader] on MCU.
|
This command programs the controller with [dfu-programmer] if the tool is intalled and configured properly.
|
||||||
$ make -f Makefile.vusb program
|
|
||||||
|
|
||||||
[AVRISPmkII]: http://www.atmel.com/tools/AVRISPMKII.aspx
|
$ make dfu
|
||||||
[avrdude]: http://www.nongnu.org/avrdude/
|
|
||||||
|
Or you can also use [FLIP] command to program. Also the tool should be intalled and configured properly. FLIP GUI app is also available.
|
||||||
|
|
||||||
|
$ make flip
|
||||||
|
|
||||||
|
Use [Teensy Loader] if your controller is Teensy/Teensy++.
|
||||||
|
|
||||||
|
|
||||||
##How to Customize
|
##How to Customize
|
||||||
@ -103,7 +76,7 @@ See [tmk_keyboard] documents.
|
|||||||
|
|
||||||
|
|
||||||
##Hardware
|
##Hardware
|
||||||
You have some options for hardware. Development boards with USB AVR family(ATMega32U4, AT90USB1286) like Teensy will work while MegaAVR with V-USB library is also cheapear option for DIY.
|
You have some options for hardware. Development boards with USB AVR family(ATMega32U4, AT90USB1286) like Teensy will work while MegaAVR with [V-USB] library is also cheapear option for DIY.
|
||||||
|
|
||||||
###1. TMK Alt Controller Board
|
###1. TMK Alt Controller Board
|
||||||
TMK designed [Keyboard Controller Board for HHKB Pro2(KiCad project)](https://github.com/tmk/HHKB_controller).
|
TMK designed [Keyboard Controller Board for HHKB Pro2(KiCad project)](https://github.com/tmk/HHKB_controller).
|
||||||
@ -127,7 +100,6 @@ See [this post](http://geekhack.org/index.php?topic=12047.msg948923#msg948923).
|
|||||||
+---------------+
|
+---------------+
|
||||||
|
|
||||||
- NOTE: PJRC [Teensy](http://www.pjrc.com/teensy/)
|
- NOTE: PJRC [Teensy](http://www.pjrc.com/teensy/)
|
||||||
[Teensy Loader]: http://www.pjrc.com/teensy/loader.html
|
|
||||||
|
|
||||||
###3. V-USB connection
|
###3. V-USB connection
|
||||||
+---+ +---------------+
|
+---+ +---------------+
|
||||||
@ -156,5 +128,11 @@ See [this post](http://geekhack.org/index.php?topic=12047.msg948923#msg948923).
|
|||||||
- NOTE: See [V-USB] documentation for more detail of hardware and the USB stack.
|
- NOTE: See [V-USB] documentation for more detail of hardware and the USB stack.
|
||||||
- NOTE: [USBaspLoader] is very useful for firmware update.
|
- NOTE: [USBaspLoader] is very useful for firmware update.
|
||||||
|
|
||||||
|
|
||||||
|
[LUFA]: http://www.fourwalledcubicle.com/LUFA.php
|
||||||
|
[PJRC]: http://www.pjrc.com/teensy/usb_keyboard.html
|
||||||
|
[dfu-programmer]: http://dfu-programmer.sourceforge.net/
|
||||||
|
[FLIP]: http://www.atmel.com/tools/FLIP.aspx
|
||||||
|
[Teensy Loader]: http://www.pjrc.com/teensy/loader.html
|
||||||
[V-USB]: http://www.obdev.at/products/vusb/index.html
|
[V-USB]: http://www.obdev.at/products/vusb/index.html
|
||||||
[USBaspLoader]: http://www.obdev.at/products/vusb/usbasploader.html
|
[USBaspLoader]: http://www.obdev.at/products/vusb/usbasploader.html
|
||||||
|
@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
#define VENDOR_ID 0xFEED
|
#define VENDOR_ID 0xFEED
|
||||||
#define PRODUCT_ID 0xCAFE
|
#define PRODUCT_ID 0xCAFE
|
||||||
#define DEVICE_VER 0x0103
|
#define DEVICE_VER 0x0104
|
||||||
#define MANUFACTURER t.m.k.
|
#define MANUFACTURER t.m.k.
|
||||||
#define PRODUCT HHKB mod
|
#define PRODUCT HHKB mod
|
||||||
#define DESCRIPTION t.m.k. keyboard firmware for HHKB mod
|
#define DESCRIPTION t.m.k. keyboard firmware for HHKB mod
|
||||||
@ -31,27 +31,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define MATRIX_ROWS 8
|
#define MATRIX_ROWS 8
|
||||||
#define MATRIX_COLS 8
|
#define MATRIX_COLS 8
|
||||||
|
|
||||||
/*
|
|
||||||
* Boot magic keys
|
|
||||||
* call some function by pressing key when pluging cable or powering on.
|
|
||||||
*/
|
|
||||||
/* key position on matrix(ROW:COL) */
|
|
||||||
#define KEY_FN 0x54
|
|
||||||
#define KEY_D 0x14
|
|
||||||
#define KEY_IS_ON(key) matrix_is_on((key)>>4, (key)&0xF)
|
|
||||||
/* kick up bootloader */
|
|
||||||
#define IS_BOOTMAGIC_BOOTLOADER() KEY_IS_ON(KEY_FN)
|
|
||||||
/* debug on */
|
|
||||||
#define IS_BOOTMAGIC_DEBUG() KEY_IS_ON(KEY_D)
|
|
||||||
|
|
||||||
|
|
||||||
/* key combination for command */
|
/* key combination for command */
|
||||||
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
|
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
|
||||||
|
|
||||||
/* mouse keys */
|
|
||||||
#ifdef MOUSEKEY_ENABLE
|
|
||||||
# define MOUSEKEY_DELAY_TIME 100
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* period of tapping(ms) */
|
/* period of tapping(ms) */
|
||||||
#define TAPPING_TERM 300
|
#define TAPPING_TERM 300
|
||||||
@ -62,11 +45,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
/* Boot Magic salt key: Space */
|
/* Boot Magic salt key: Space */
|
||||||
#define BOOTMAGIC_KEY_SALT KC_FN6
|
#define BOOTMAGIC_KEY_SALT KC_FN6
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Feature disable options
|
* Feature disable options
|
||||||
* These options are also useful to firmware size reduction.
|
* These options are also useful to firmware size reduction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* disable debug print */
|
/* disable debug print */
|
||||||
//#define NO_DEBUG
|
//#define NO_DEBUG
|
||||||
|
|
||||||
|
@ -57,9 +57,11 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
|||||||
HID_RI_REPORT_COUNT(8, 0x08),
|
HID_RI_REPORT_COUNT(8, 0x08),
|
||||||
HID_RI_REPORT_SIZE(8, 0x01),
|
HID_RI_REPORT_SIZE(8, 0x01),
|
||||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||||
|
|
||||||
HID_RI_REPORT_COUNT(8, 0x01),
|
HID_RI_REPORT_COUNT(8, 0x01),
|
||||||
HID_RI_REPORT_SIZE(8, 0x08),
|
HID_RI_REPORT_SIZE(8, 0x08),
|
||||||
HID_RI_INPUT(8, HID_IOF_CONSTANT),
|
HID_RI_INPUT(8, HID_IOF_CONSTANT), /* reserved */
|
||||||
|
|
||||||
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
||||||
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
|
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
|
||||||
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
|
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
|
||||||
@ -69,6 +71,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
|||||||
HID_RI_REPORT_COUNT(8, 0x01),
|
HID_RI_REPORT_COUNT(8, 0x01),
|
||||||
HID_RI_REPORT_SIZE(8, 0x03),
|
HID_RI_REPORT_SIZE(8, 0x03),
|
||||||
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
|
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
|
||||||
|
|
||||||
HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */
|
HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */
|
||||||
HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */
|
HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */
|
||||||
HID_RI_USAGE_MAXIMUM(8, 0xFF), /* Keyboard Application */
|
HID_RI_USAGE_MAXIMUM(8, 0xFF), /* Keyboard Application */
|
||||||
@ -210,11 +213,13 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
|
|||||||
|
|
||||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||||
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
|
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
|
||||||
HID_RI_USAGE_MAXIMUM(8, NKRO_SIZE*8-1), /* Keyboard Right GUI */
|
HID_RI_USAGE_MAXIMUM(8, (NKRO_EPSIZE-1)*8-1), /* Keyboard Right GUI */
|
||||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||||
HID_RI_REPORT_COUNT(8, NKRO_SIZE*8),
|
HID_RI_REPORT_COUNT(8, (NKRO_EPSIZE-1)*8),
|
||||||
HID_RI_REPORT_SIZE(8, 0x01),
|
HID_RI_REPORT_SIZE(8, 0x01),
|
||||||
|
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||||
|
HID_RI_END_COLLECTION(0),
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -439,6 +444,48 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||||||
.PollingIntervalMS = 0x01
|
.PollingIntervalMS = 0x01
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NKRO
|
||||||
|
*/
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
.NKRO_Interface =
|
||||||
|
{
|
||||||
|
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||||
|
|
||||||
|
.InterfaceNumber = NKRO_INTERFACE,
|
||||||
|
.AlternateSetting = 0x00,
|
||||||
|
|
||||||
|
.TotalEndpoints = 1,
|
||||||
|
|
||||||
|
.Class = HID_CSCP_HIDClass,
|
||||||
|
.SubClass = HID_CSCP_NonBootSubclass,
|
||||||
|
.Protocol = HID_CSCP_NonBootProtocol,
|
||||||
|
|
||||||
|
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||||
|
},
|
||||||
|
|
||||||
|
.NKRO_HID =
|
||||||
|
{
|
||||||
|
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||||
|
|
||||||
|
.HIDSpec = VERSION_BCD(01.11),
|
||||||
|
.CountryCode = 0x00,
|
||||||
|
.TotalReportDescriptors = 1,
|
||||||
|
.HIDReportType = HID_DTYPE_Report,
|
||||||
|
.HIDReportLength = sizeof(NKROReport)
|
||||||
|
},
|
||||||
|
|
||||||
|
.NKRO_INEndpoint =
|
||||||
|
{
|
||||||
|
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||||
|
|
||||||
|
.EndpointAddress = (ENDPOINT_DIR_IN | NKRO_IN_EPNUM),
|
||||||
|
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||||
|
.EndpointSize = NKRO_EPSIZE,
|
||||||
|
.PollingIntervalMS = 0x01
|
||||||
|
},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -535,6 +582,12 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
|||||||
Address = &ConfigurationDescriptor.Console_HID;
|
Address = &ConfigurationDescriptor.Console_HID;
|
||||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
case NKRO_INTERFACE:
|
||||||
|
Address = &ConfigurationDescriptor.NKRO_HID;
|
||||||
|
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -561,6 +614,12 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
|||||||
Address = &ConsoleReport;
|
Address = &ConsoleReport;
|
||||||
Size = sizeof(ConsoleReport);
|
Size = sizeof(ConsoleReport);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
case NKRO_INTERFACE:
|
||||||
|
Address = &NKROReport;
|
||||||
|
Size = sizeof(NKROReport);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 Jun Wako <wakojun@gmail.com>
|
* Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
|
||||||
* This file is based on:
|
* This file is based on:
|
||||||
* LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
|
* LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
|
||||||
* LUFA-120219/Demos/Device/Lowlevel/GenericHID
|
* LUFA-120219/Demos/Device/Lowlevel/GenericHID
|
||||||
@ -78,6 +78,13 @@ typedef struct
|
|||||||
USB_Descriptor_Endpoint_t Console_INEndpoint;
|
USB_Descriptor_Endpoint_t Console_INEndpoint;
|
||||||
USB_Descriptor_Endpoint_t Console_OUTEndpoint;
|
USB_Descriptor_Endpoint_t Console_OUTEndpoint;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
// NKRO HID Interface
|
||||||
|
USB_Descriptor_Interface_t NKRO_Interface;
|
||||||
|
USB_HID_Descriptor_HID_t NKRO_HID;
|
||||||
|
USB_Descriptor_Endpoint_t NKRO_INEndpoint;
|
||||||
|
#endif
|
||||||
} USB_Descriptor_Configuration_t;
|
} USB_Descriptor_Configuration_t;
|
||||||
|
|
||||||
|
|
||||||
@ -102,9 +109,15 @@ typedef struct
|
|||||||
# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
|
# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
# define NKRO_INTERFACE (CONSOLE_INTERFACE + 1)
|
||||||
|
#else
|
||||||
|
# define NKRO_INTERFACE CONSOLE_INTERFACE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* nubmer of interfaces */
|
/* nubmer of interfaces */
|
||||||
#define TOTAL_INTERFACES (CONSOLE_INTERFACE + 1)
|
#define TOTAL_INTERFACES (NKRO_INTERFACE + 1)
|
||||||
|
|
||||||
|
|
||||||
// Endopoint number and size
|
// Endopoint number and size
|
||||||
@ -125,6 +138,12 @@ typedef struct
|
|||||||
#ifdef CONSOLE_ENABLE
|
#ifdef CONSOLE_ENABLE
|
||||||
# define CONSOLE_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1)
|
# define CONSOLE_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1)
|
||||||
# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
|
# 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)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -132,6 +151,7 @@ typedef struct
|
|||||||
#define MOUSE_EPSIZE 8
|
#define MOUSE_EPSIZE 8
|
||||||
#define EXTRAKEY_EPSIZE 8
|
#define EXTRAKEY_EPSIZE 8
|
||||||
#define CONSOLE_EPSIZE 32
|
#define CONSOLE_EPSIZE 32
|
||||||
|
#define NKRO_EPSIZE 16
|
||||||
|
|
||||||
|
|
||||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||||
|
@ -220,6 +220,12 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
|||||||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
|
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
|
||||||
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
/* Setup NKRO HID Report Endpoints */
|
||||||
|
ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||||
|
NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -350,15 +356,31 @@ static void send_keyboard(report_keyboard_t *report)
|
|||||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: handle NKRO report
|
|
||||||
/* Select the Keyboard Report Endpoint */
|
/* Select the Keyboard Report Endpoint */
|
||||||
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
|
#ifdef NKRO_ENABLE
|
||||||
|
if (keyboard_nkro) {
|
||||||
|
Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if Keyboard Endpoint Ready for Read/Write */
|
/* Check if Keyboard Endpoint Ready for Read/Write */
|
||||||
while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
|
while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
|
||||||
|
|
||||||
/* Write Keyboard Report Data */
|
/* Write Keyboard Report Data */
|
||||||
Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL);
|
#ifdef NKRO_ENABLE
|
||||||
|
if (keyboard_nkro) {
|
||||||
|
Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* boot mode */
|
||||||
|
Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Finalize the stream transfer to send the last packet */
|
/* Finalize the stream transfer to send the last packet */
|
||||||
Endpoint_ClearIN();
|
Endpoint_ClearIN();
|
||||||
|
@ -57,12 +57,12 @@ int8_t usb_keyboard_send_report(report_keyboard_t *report)
|
|||||||
|
|
||||||
#ifdef NKRO_ENABLE
|
#ifdef NKRO_ENABLE
|
||||||
if (keyboard_nkro)
|
if (keyboard_nkro)
|
||||||
result = send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS);
|
result = send_report(report, KBD2_ENDPOINT, 0, KBD2_SIZE);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (usb_keyboard_protocol)
|
if (usb_keyboard_protocol)
|
||||||
result = send_report(report, KBD_ENDPOINT, 0, KBD_REPORT_KEYS);
|
result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE);
|
||||||
else
|
else
|
||||||
result = send_report(report, KBD_ENDPOINT, 0, 6);
|
result = send_report(report, KBD_ENDPOINT, 0, 6);
|
||||||
}
|
}
|
||||||
@ -104,15 +104,8 @@ static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, ui
|
|||||||
cli();
|
cli();
|
||||||
UENUM = endpoint;
|
UENUM = endpoint;
|
||||||
}
|
}
|
||||||
UEDATX = report->mods;
|
|
||||||
#ifdef NKRO_ENABLE
|
|
||||||
if (!keyboard_nkro)
|
|
||||||
UEDATX = 0;
|
|
||||||
#else
|
|
||||||
UEDATX = 0;
|
|
||||||
#endif
|
|
||||||
for (uint8_t i = keys_start; i < keys_end; i++) {
|
for (uint8_t i = keys_start; i < keys_end; i++) {
|
||||||
UEDATX = report->keys[i];
|
UEDATX = report->raw[i];
|
||||||
}
|
}
|
||||||
UEINTX = 0x3A;
|
UEINTX = 0x3A;
|
||||||
SREG = intr_state;
|
SREG = intr_state;
|
||||||
|
Loading…
Reference in New Issue
Block a user