~ruther/qmk_firmware

9307a0a3e415d33d0858283f67fcba4c59a042ff — Jack Humbert 10 years ago be86aef + c35c428
Merge pull request #6 from tmk/master

pulling from tmk
64 files changed, 2435 insertions(+), 1614 deletions(-)

M README.md
M common/avr/suspend.c
M common/command.c
M common/suspend.h
M converter/adb_usb/README.md
M doc/keycode.txt
M doc/other_projects.md
R keyboard/{hhkb/Makefile.nodebug => ghost_squid/Makefile.lufa}
A keyboard/ghost_squid/README.md
A keyboard/ghost_squid/config.h
A keyboard/ghost_squid/keymap.c
A keyboard/ghost_squid/keymap_ansi.h
A keyboard/ghost_squid/led.c
A keyboard/ghost_squid/matrix.c
R keyboard/{hhkb_rn42/Makefile => hhkb/Makefile.rn42}
M keyboard/hhkb/README.md
R keyboard/{hhkb_rn42/config => hhkb/config_rn42}.h
M keyboard/hhkb/hhkb_avr.h
M keyboard/hhkb/keymap_hasu.c
M keyboard/hhkb/matrix.c
R keyboard/hhkb/{ => not_supported}/Makefile.iwrap
R keyboard/hhkb/{ => not_supported}/Makefile.vusb
R keyboard/hhkb/{ => not_supported}/config_iwrap.h
R keyboard/hhkb/{ => not_supported}/config_vusb.h
R keyboard/hhkb/{ => not_supported}/iwrap.txt
R keyboard/hhkb/{ => not_supported}/usbconfig.h
R keyboard/{hhkb_rn42 => hhkb}/rn42.mk
A keyboard/hhkb/rn42/MEMO.txt
R keyboard/{hhkb_rn42 => hhkb/rn42}/PowerSave.txt
A keyboard/hhkb/rn42/RN42.txt
R keyboard/{hhkb_rn42 => hhkb}/rn42/battery.c
R keyboard/{hhkb_rn42 => hhkb}/rn42/battery.h
R keyboard/{hhkb_rn42 => hhkb}/rn42/main.c
R keyboard/{hhkb_rn42 => hhkb}/rn42/rn42.c
R keyboard/{hhkb_rn42 => hhkb}/rn42/rn42.h
R keyboard/{hhkb_rn42 => hhkb}/rn42/rn42_task.c
R keyboard/{hhkb_rn42 => hhkb}/rn42/rn42_task.h
R keyboard/{hhkb_rn42 => hhkb}/rn42/suart.S
R keyboard/{hhkb_rn42 => hhkb}/rn42/suart.h
D keyboard/hhkb_rn42/MEMO.txt
D keyboard/hhkb_rn42/hhkb_avr.h
D keyboard/hhkb_rn42/keymap_common.h
D keyboard/hhkb_rn42/keymap_hasu.c
D keyboard/hhkb_rn42/keymap_jp.c
D keyboard/hhkb_rn42/led.c
D keyboard/hhkb_rn42/matrix.c
M keyboard/infinity/Makefile
M keyboard/infinity/config.h
M keyboard/infinity/keymap.c
M keyboard/infinity/keymap_common.h
A keyboard/nerd/Makefile
A keyboard/nerd/README.md
A keyboard/nerd/backlight.c
A keyboard/nerd/backlight.h
A keyboard/nerd/config.h
A keyboard/nerd/keymap_60_ansi150.c
A keyboard/nerd/keymap_80_ansi150.c
R keyboard/{hhkb_rn42 => nerd}/keymap_common.c
A keyboard/nerd/keymap_common.h
A keyboard/nerd/matrix.c
M protocol/adb.c
M protocol/bluefruit/main.c
M protocol/lufa/lufa.c
M protocol/pjrc/main.c
M README.md => README.md +16 -1
@@ 54,6 54,15 @@ You can find some keyboard specific projects under `converter` and `keyboard` di
* [KMAC](keyboard/kmac/)                    - Korean custom keyboard
* [Lightsaber](keyboard/lightsaber/)        - Korean custom keyboard
* [Infinity](keyboard/infinity/)            - Massdrop [Infinity keyboard][Infinity]
* [NerD](keyboard/nerd/)                    - Korean custom keyboard
* [KittenPaw](keyboard/kitten_paw)          - Custom Majestouch controller
* [Lightpad](keyboard/lightpad)             - Korean custom keypad
* [ghost_squid](keyboard/ghost_squid/)      - [The Ghost Squid][ghost_squid] controller for [Cooler Master QuickFire XT][cmxt]

### Extenal projects using tmk_keyboard
* [ErgoDox_cub-uanic][cub-uanic]            - Split Ergonomic Keyboard [ErgoDox][ergodox_org]
* [mcdox][mcdox_tmk]                        - [mcdox][mcdox]


[GH_macway]:    http://geekhack.org/showwiki.php?title=Island:11930
[GH_hhkb]:      http://geekhack.org/showwiki.php?title=Island:12047


@@ 74,6 83,12 @@ You can find some keyboard specific projects under `converter` and `keyboard` di
[Sun]:          http://en.wikipedia.org/wiki/Sun-3
[IIGS]:         http://en.wikipedia.org/wiki/Apple_IIGS
[Infinity]:     https://www.massdrop.com/buy/infinity-keyboard-kit
[ghost_squid]:  http://deskthority.net/wiki/Costar_replacement_controllers#The_Ghost_Squid
[cmxt]:         http://gaming.coolermaster.com/en/products/keyboards/quickfirext/
[ergodox_org]:  http://ergodox.org/
[cub-uanic]:    https://github.com/cub-uanic/tmk_keyboard/tree/master/keyboard/ergodox
[mcdox]:        https://github.com/DavidMcEwan/mcdox
[mcdox_tmk]:    https://github.com/DavidMcEwan/tmk_keyboard/tree/master/keyboard/mcdox





@@ 278,4 293,4 @@ Coding Style

Other Keyboard Firmware Projects
------------------
See [doc/other_projects.md](doc/other_projects.md).
You can learn a lot about keyboard firmware from these. See [doc/other_projects.md](doc/other_projects.md).

M common/avr/suspend.c => common/avr/suspend.c +16 -11
@@ 7,6 7,7 @@
#include "backlight.h"
#include "suspend_avr.h"
#include "suspend.h"
#include "timer.h"
#ifdef PROTOCOL_LUFA
#include "lufa.h"
#endif


@@ 52,11 53,13 @@ void suspend_idle(uint8_t time)
 *          WDTO_4S
 *          WDTO_8S
 */
void suspend_power_down(uint8_t wdto)
static uint8_t wdt_timeout = 0;
static void power_down(uint8_t wdto)
{
#ifdef PROTOCOL_LUFA
    if (USB_DeviceState == DEVICE_STATE_Configured) return;
#endif
    wdt_timeout = wdto;

    // Watchdog Interrupt Mode
    wdt_intr_enable(wdto);


@@ 67,7 70,6 @@ void suspend_power_down(uint8_t wdto)
    // - prescale clock
    // - BOD disable
    // - Power Reduction Register PRR

    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sei();


@@ 78,6 80,11 @@ void suspend_power_down(uint8_t wdto)
    wdt_disable();
}

void suspend_power_down(void)
{
    power_down(WDTO_15MS);
}

bool suspend_wakeup_condition(void)
{
    matrix_power_up();


@@ 103,15 110,13 @@ void suspend_wakeup_init(void)
/* watchdog timeout */
ISR(WDT_vect)
{
    /* wakeup from MCU sleep mode */
/*
    // blink LED
    static uint8_t led_state = 0;
    static uint8_t led_count = 0;
    led_count++;
    if ((led_count & 0x07) == 0) {
        led_set((led_state ^= (1<<USB_LED_CAPS_LOCK)));
    // compensate timer for sleep
    switch (wdt_timeout) {
        case WDTO_15MS:
            timer_count += 15 + 2;  // WDTO_15MS + 2(from observation)
            break;
        default:
            ;
    }
*/
}
#endif

M common/command.c => common/command.c +6 -6
@@ 303,7 303,7 @@ static bool command_common(uint8_t code)
#endif
            " " STR(BOOTLOADER_SIZE) "\n");

            print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__) 
            print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
                  " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
                  " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n");
            break;


@@ 542,12 542,12 @@ static void mousekey_console_help(void)
    print("4:	select mk_time_to_max\n");
    print("5:	select mk_wheel_max_speed\n");
    print("6:	select mk_wheel_time_to_max\n");
    print("p:	print prameters\n");
    print("p:	print parameters\n");
    print("d:	set default values\n");
    print("up:	increase prameters(+1)\n");
    print("down:	decrease prameters(-1)\n");
    print("pgup:	increase prameters(+10)\n");
    print("pgdown:	decrease prameters(-10)\n");
    print("up:	increase parameters(+1)\n");
    print("down:	decrease parameters(-1)\n");
    print("pgup:	increase parameters(+10)\n");
    print("pgdown:	decrease parameters(-10)\n");
    print("\nspeed = delta * max_speed * (repeat / time_to_max)\n");
    print("where delta: cursor="); pdec(MOUSEKEY_MOVE_DELTA);
    print(", wheel="); pdec(MOUSEKEY_WHEEL_DELTA); print("\n");

M common/suspend.h => common/suspend.h +1 -1
@@ 6,7 6,7 @@


void suspend_idle(uint8_t timeout);
void suspend_power_down(uint8_t timeout);
void suspend_power_down(void);
bool suspend_wakeup_condition(void);
void suspend_wakeup_init(void);


M converter/adb_usb/README.md => converter/adb_usb/README.md +1 -1
@@ 88,7 88,7 @@ modifiers except for GUI key(Windows/Command).
And most ADB keyboard has no diodes in its matrix so they are not NKRO,
though ADB protocol itself supports it. See protocol/adb.c for more info.

If keyobard has ISO layout you need to use ISO keymap with `make KEYMAP=iso`. With ANSI
If keyboard has ISO layout you need to use ISO keymap with `make KEYMAP=iso`. With ANSI
keymap you will suffer from swapped keys problem.

https://github.com/tmk/tmk_keyboard/issues/35

M doc/keycode.txt => doc/keycode.txt +1 -1
@@ 81,7 81,7 @@ KC_F12                              45 Keyboard F12
KC_PSCREEN          KC_PSCR         46 Keyboard PrintScreen1
KC_SCKLOCK          KC_SLCK         47 Keyboard Scroll Lock11
KC_PAUSE            KC_PAUS         48 Keyboard Pause1
KC_INSERT           KC_INT          49 Keyboard Insert1
KC_INSERT           KC_INS          49 Keyboard Insert1
KC_HOME                             4A Keyboard Home1
KC_PGUP                             4B Keyboard PageUp1
KC_DELETE           KC_DELETE       4C Keyboard Delete Forward

M doc/other_projects.md => doc/other_projects.md +1 -0
@@ 29,6 29,7 @@ Other Keyboard Firmware Projects
## ErgoDox[Ergo][Split][USB][AVR]
- <http://geekhack.org/index.php?topic=22780.0>
- <https://github.com/benblazak/ergodox-firmware>
- <https://github.com/cub-uanic/tmk_keyboard>

## Suka's keyboard collection[Ergo][Split][3DPrinting][USB][AVR]
- <http://deskthority.net/workshop-f7/my-diy-keyboard-collection-or-how-i-became-a-kb-geek-t2534.html>

R keyboard/hhkb/Makefile.nodebug => keyboard/ghost_squid/Makefile.lufa +16 -40
@@ 39,7 39,7 @@
#----------------------------------------------------------------------------

# Target file name (without extension).
TARGET = hhkb_lufa
TARGET = ghostsquid_lufa

# Directory common source filess exist
TOP_DIR = ../..


@@ 47,26 47,15 @@ TOP_DIR = ../..
# Directory keyboard dependent files exist
TARGET_DIR = .


# List C source files here. (C dependencies are automatically generated.)
SRC +=	keymap_common.c \
SRC =	keymap.c \
	matrix.c \
	led.c

ifdef KEYMAP
    SRC := keymap_$(KEYMAP).c $(SRC)
else
    SRC := keymap_hasu.c $(SRC)
endif

CONFIG_H = config.h


# MCU name
# PJRC Teensy++ 2.0
#MCU = at90usb1286
# TMK Alt Controller or PJRC Teensy 2.0
MCU = atmega32u4
MCU = atmega32u2

# Processor frequency.
#     This will define a symbol, F_CPU, in all source code files equal to the


@@ 81,7 70,6 @@ MCU = atmega32u4
#     software delays.
F_CPU = 16000000


#
# LUFA specific
#


@@ 101,31 89,25 @@ 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
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT


# Boot Section Size in *bytes*
#   Teensy halfKay   512
#   Teensy++ halfKay 1024
#   Atmel DFU loader 4096	(TMK Alt Controller)
#   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
KEYMAP_SECTION_ENABLE = yes	# fixed address keymap for keymap editor
#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


# 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)


@@ 133,9 115,3 @@ VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk

debug-on: EXTRAFLAGS += -DDEBUG -DDEBUG_ACTION
debug-on: all

debug-off: EXTRAFLAGS += -DNO_DEBUG -DNO_PRINT
debug-off: all

A keyboard/ghost_squid/README.md => keyboard/ghost_squid/README.md +20 -0
@@ 0,0 1,20 @@
The Ghost Squid controller
==========================
Custom controller for the Cooler Master QuickFire XT keyboard designed by bpiphany.

*Note that this is not the official firmware*

Build
-----
Move to this directory then just run `make` like:

    $ make -f Makefile.lufa

At the moment only the LUFA stack is supported.


Bootloader
---------
To enter bootloader by hardware use a magnet above the controller before connecting the usb cable.

It is still possible to use Boot Magic and Command (LSFT+RSFT+PAUS) to access the bootloader though.

A keyboard/ghost_squid/config.h => keyboard/ghost_squid/config.h +43 -0
@@ 0,0 1,43 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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 // 0x2516 (original CM XT value)
#define PRODUCT_ID      0x001A
#define DEVICE_VER      0x0000
#define MANUFACTURER    Cooler Master
#define PRODUCT         Cooler Master QuickFire XT

/* message strings */
#define DESCRIPTION     t.m.k. keyboard firmware for Cooler Master QuickFire XT

/* matrix size */
#define MATRIX_ROWS 8
#define MATRIX_COLS 18

/* 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

A keyboard/ghost_squid/keymap.c => keyboard/ghost_squid/keymap.c +102 -0
@@ 0,0 1,102 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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/pgmspace.h>
#include "keycode.h"
#include "action.h"
#include "action_macro.h"
#include "report.h"
#include "host.h"
#include "debug.h"
#include "keymap.h"

/*
 Matrix col/row mapping

 ,----.    ,-------------------. ,-------------------. ,-------------------. ,--------------.
 |06/6|    |07/4|08/4|08/2|08/6| |15/5|11/6|12/2|12/4| |14/4|14/5|14/6|14/0| |13/5|13/7|15/7|
 `----'    `-------------------' `-------------------' `-------------------' `--------------'
 ,-------------------------------------------------------------------------. ,--------------. ,-------------------.
 |06/4|06/5|07/5|08/5|09/5|09/4|10/4|10/5|11/5|12/5|05/5|05/4|11/4|    14/2| |17/4|02/4|04/4| |16/1|17/1|04/1|04/0|
 |-------------------------------------------------------------------------| |--------------| |-------------------|
 |06/2  |06/7|07/7|08/7|09/7|09/2|10/2|10/7|11/7|12/7|05/7|05/2|11/2|  14/3| |16/4|02/5|04/5| |16/7|17/7|04/7|    |
 |-------------------------------------------------------------------------| '--------------' |-------------- 02/7|
 |02/7   |06/3|07/3|08/3|09/3|09/6|10/6|10/3|11/3|12/3|05/3|05/6|      14/1|                  |16/2|17/2|04/2|    |
 |-------------------------------------------------------------------------|      ,----.      |-------------------|
 |01/2     |06/1|07/1|08/1|09/1|09/0|10/0|10/1|11/1|12/1|05/0|         01/3|      |02/6|      |16/3|17/3|04/3|    |
 |-------------------------------------------------------------------------| ,--------------. |-------------- 02/3|
 |15/4|03/2|13/6|                 16/6                  |13/0|0/3|12/0|15/1| |02/0|16/0|17/0| | 17/6    |04/6|    |
 `-------------------------------------------------------------------------' `--------------' `-------------------'
*/

#define KEYMAP( \
    KG6,      KH4, KI4, KI2, KI6, KP5, KL6, KM2, KM4, KO4, KO5, KO6, KO0,   KN5, KN7, KP7,                       \
    KG4, KG5, KH5, KI5, KJ5, KJ4, KK4, KK5, KL5, KM5, KF5, KF4, KL4, KO2,   KR4, KC4, KE4,   KQ1, KR1, KE1, KE0, \
    KG2, KG7, KH7, KI7, KJ7, KJ2, KK2, KK7, KL7, KM7, KF7, KF2, KL2, KO3,   KQ4, KC5, KE5,   KQ7, KR7, KE7, KC7, \
    KH2, KG3, KH3, KI3, KJ3, KJ6, KK6, KK3, KL3, KM3, KF3, KF6,      KO1,                    KQ2, KR2, KE2,      \
    KB2, KH6, KG1, KH1, KI1, KJ1, KJ0, KK0, KK1, KL1, KM1, KF0,      KB3,        KC6,        KQ3, KR3, KE3, KC3, \
    KP4, KD2, KN6,                KQ6,                KN0, KA3, KM0, KP1,   KC0, KQ0, KR0,   KR6,      KE6       \
) { \
/*            0         1         2         3         4         5         6         7   */  \
/* A  0 */ {KC_NO,    KC_NO,    KC_NO,    KC_##KA3, KC_NO,    KC_NO,    KC_NO,    KC_NO   },\
/* B  1 */ {KC_NO,    KC_NO,    KC_##KB2, KC_##KB3, KC_NO,    KC_NO,    KC_NO,    KC_NO   },\
/* C  2 */ {KC_##KC0, KC_NO,    KC_NO,    KC_##KC3, KC_##KC4, KC_##KC5, KC_##KC6, KC_##KC7},\
/* D  3 */ {KC_NO,    KC_NO,    KC_##KD2, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO   },\
/* E  4 */ {KC_##KE0, KC_##KE1, KC_##KE2, KC_##KE3, KC_##KE4, KC_##KE5, KC_##KE6, KC_##KE7},\
/* F  5 */ {KC_##KF0, KC_NO,    KC_##KF2, KC_##KF3, KC_##KF4, KC_##KF5, KC_##KF6, KC_##KF7},\
/* G  6 */ {KC_NO,    KC_##KG1, KC_##KG2, KC_##KG3, KC_##KG4, KC_##KG5, KC_##KG6, KC_##KG7},\
/* H  7 */ {KC_NO,    KC_##KH1, KC_##KH2, KC_##KH3, KC_##KH4, KC_##KH5, KC_##KH6, KC_##KH7},\
/* I  8 */ {KC_NO,    KC_##KI1, KC_##KI2, KC_##KI3, KC_##KI4, KC_##KI5, KC_##KI6, KC_##KI7},\
/* J  9 */ {KC_##KJ0, KC_##KJ1, KC_##KJ2, KC_##KJ3, KC_##KJ4, KC_##KJ5, KC_##KJ6, KC_##KJ7},\
/* K 10 */ {KC_##KK0, KC_##KK1, KC_##KK2, KC_##KK3, KC_##KK4, KC_##KK5, KC_##KK6, KC_##KK7},\
/* L 11 */ {KC_NO,    KC_##KL1, KC_##KL2, KC_##KL3, KC_##KL4, KC_##KL5, KC_##KL6, KC_##KL7},\
/* M 12 */ {KC_##KM0, KC_##KM1, KC_##KM2, KC_##KM3, KC_##KM4, KC_##KM5, KC_NO,    KC_##KM7},\
/* N 13 */ {KC_##KN0, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_##KN5, KC_##KN6, KC_##KN7},\
/* O 14 */ {KC_##KO0, KC_##KO1, KC_##KO2, KC_##KO3, KC_##KO4, KC_##KO5, KC_##KO6, KC_NO   },\
/* P 15 */ {KC_NO,    KC_##KP1, KC_NO,    KC_NO,    KC_##KP4, KC_##KP5, KC_NO,    KC_##KP7},\
/* Q 16 */ {KC_##KQ0, KC_##KQ1, KC_##KQ2, KC_##KQ3, KC_##KQ4, KC_NO,    KC_##KQ6, KC_##KQ7},\
/* R 17 */ {KC_##KR0, KC_##KR1, KC_##KR2, KC_##KR3, KC_##KR4, KC_NO,    KC_##KR6, KC_##KR7} \
}

#include "keymap_ansi.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, keypos_t key)
{
    if (layer < KEYMAPS_SIZE) {
        return pgm_read_byte(&keymaps[(layer)][(key.col)][(key.row)]);
    } else {
        return pgm_read_byte(&keymaps[0][(key.col)][(key.row)]);
    }
}

/* 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;
}

A keyboard/ghost_squid/keymap_ansi.h => keyboard/ghost_squid/keymap_ansi.h +23 -0
@@ 0,0 1,23 @@

static const uint8_t PROGMEM keymaps[][MATRIX_COLS][MATRIX_ROWS] = {
    /* Layer 0: Standard ANSI layer */
    KEYMAP(\
         ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11,  F12,        PSCR,SLCK,PAUS,                         \
         GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS, EQL,BSPC,   INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS, \
         TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS,   DEL, END, PGDN,    P7,  P8,  P9,  PPLS, \
         CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,      ENT,                      P4,  P5,  P6,        \
         LSFT,NUBS,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,     RSFT,        UP,           P1,  P2,  P3,  PENT, \
         LCTL,LGUI,LALT,               SPC,                RALT,RGUI, FN0,RCTL,   LEFT,DOWN,RGHT,    P0,  PDOT),          \
    /* Layer 1: Function layer */
    KEYMAP(\
         CALC,MYCM,WSCH,WHOM,MAIL,VOLD,VOLU,MSEL,MSTP,MPLY,MPRV,MNXT,TRNS,        WAKE, PWR,SLEP,                         \
         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,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,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)
};

A keyboard/ghost_squid/led.c => keyboard/ghost_squid/led.c +60 -0
@@ 0,0 1,60 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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
 *
 * Scroll Lock  PB7
 * CAPS         PC6
 * NUMLOCK      PC5
 *
 */
void led_set(uint8_t usb_led)
{
    DDRB |= (1<<7);
    DDRC |= (1<<5) | (1<<6);

    if (usb_led & (1<<USB_LED_CAPS_LOCK))
    {
        PORTC &= ~(1<<6);
    }
    else
    {
        PORTC |= (1<<6);
    }

    if (usb_led & (1<<USB_LED_NUM_LOCK))
    {
        PORTC &= ~(1<<5);
    }
    else
    {
        PORTC |= (1<<5);
    }

    if (usb_led & (1<<USB_LED_SCROLL_LOCK))
    {
        PORTB &= ~(1<<7);
    }
    else
    {
        PORTB |= (1<<7);
    }
}

A keyboard/ghost_squid/matrix.c => keyboard/ghost_squid/matrix.c +237 -0
@@ 0,0 1,237 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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;

static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t matrix_debouncing[MATRIX_ROWS];

static uint8_t read_rows(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();
    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++) {
        select_col(col);
        _delay_us(3);
        uint8_t rows = read_rows();
        for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
            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);
                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    6    7
 * pin: PB1  PC2  PB6  PB4  PB3  PB5  PB0  PB2
 *
 */
static void init_rows(void)
{
    DDRC &= ~0b00000100;
    DDRB &= ~0b01111111;
    PORTC |= 0b00000100;
    PORTB |= 0b01111111;
}

static uint8_t read_rows(void)
{
    return (PINB&(1<<1) ? 0 : (1<<0)) |
           (PINC&(1<<2) ? 0 : (1<<1)) |
           (PINB&(1<<6) ? 0 : (1<<2)) |
           (PINB&(1<<4) ? 0 : (1<<3)) |
           (PINB&(1<<3) ? 0 : (1<<4)) |
           (PINB&(1<<5) ? 0 : (1<<5)) |
           (PINB&(1<<0) ? 0 : (1<<6)) |
           (PINB&(1<<2) ? 0 : (1<<7));
}

/*  These columns uses two 74HC42 4 to 10 bit demultiplexers (low active).
 *
 *   COL PD6 PD5 PD4 PD3 PD2 PD1
 *   10   1   1   0   0   0   0
 *   15   1   1   0   0   0   1
 *    8   1   1   0   0   1   0
 *   14   1   1   0   1   0   0
 *    6   1   1   0   1   0   1
 *   13   1   1   0   1   1   0
 *   12   1   1   1   0   0   0
 *    9   1   1   1   0   1   0
 *   11   1   1   1   1   0   0
 *    7   1   1   1   1   1   0
 *
 *   COL PD1 PD2 PD3 PD4 PD5 PD6
 *    3   1   1   0   0   0   1
 *    4   1   1   0   0   1   0
 *   17   1   1   0   1   0   0
 *   16   1   1   0   1   1   0
 *    0   1   1   1   0   0   1
 *    5   1   1   1   0   1   0
 *    2   1   1   1   1   0   0
 *    1   1   1   1   1   1   0
 */
static void unselect_cols(void)
{
    DDRD |= 0b01111111;
    PORTD &= ~0b01111111;
}

static void select_col(uint8_t col)
{
    switch (col) {
        case 0:
            PORTD |= (1<<6) | (1<<3) | (1<<2) | (1<<1);
            break;
        case 1:
            PORTD |= (1<<5) | (1<<4) | (1<<3) | (1<<2) | (1<<1);
            break;
        case 2:
            PORTD |= (1<<4) | (1<<3) | (1<<2) | (1<<1);
            break;
        case 3:
            PORTD |= (1<<6) | (1<<2) | (1<<1);
            break;
        case 4:
            PORTD |= (1<<5) | (1<<2) | (1<<1);
            break;
        case 5:
            PORTD |= (1<<5) | (1<<3) | (1<<2) | (1<<1);
            break;
        case 6:
            PORTD |= (1<<6) | (1<<5) | (1<<3) | (1<<1);
            break;
        case 7:
            PORTD |= (1<<6) | (1<<5) | (1<<4) | (1<<3) | (1<<2);
            break;
        case 8:
            PORTD |= (1<<6) | (1<<5) | (1<<2);
            break;
        case 9:
            PORTD |= (1<<6) | (1<<5) | (1<<4) | (1<<2);
            break;
        case 10:
            PORTD |= (1<<6) | (1<<5);
            break;
        case 11:
            PORTD |= (1<<6) | (1<<5) | (1<<4) | (1<<3);
            break;
        case 12:
            PORTD |= (1<<6) | (1<<5) | (1<<4);
            break;
        case 13:
            PORTD |= (1<<6) | (1<<5) | (1<<3) | (1<<2);
            break;
        case 14:
            PORTD |= (1<<6) | (1<<5) | (1<<3);
            break;
        case 15:
            PORTD |= (1<<6) | (1<<5) | (1<<1);
            break;
        case 16:
            PORTD |= (1<<5) | (1<<4) | (1<<2) | (1<<1);
            break;
        case 17:
            PORTD |= (1<<4) | (1<<2) | (1<<1);
            break;
    }
}

R keyboard/hhkb_rn42/Makefile => keyboard/hhkb/Makefile.rn42 +10 -12
@@ 39,7 39,7 @@
#----------------------------------------------------------------------------

# Target file name (without extension).
TARGET = hhkb_lufa
TARGET = hhkb_rn42

# Directory common source filess exist
TOP_DIR = ../..


@@ 53,13 53,10 @@ SRC +=	keymap_common.c \
	matrix.c \
	led.c

CONFIG_H = config.h
CONFIG_H = config_rn42.h


# MCU name
# PJRC Teensy++ 2.0
#MCU = at90usb1286
# TMK Alt Controller or PJRC Teensy 2.0
MCU = atmega32u4

# Processor frequency.


@@ 121,11 118,6 @@ COMMAND_ENABLE = yes    	# Commands for debug and configuration
#HHKB_JP = yes			# HHKB JP support


ifdef HHKB_JP
    OPT_DEFS += -DHHKB_JP
endif


#
# Keymap file
#


@@ 134,12 126,17 @@ ifdef KEYMAP
else
    ifdef HHKB_JP
    	SRC := keymap_jp.c $(SRC)
    else
	SRC := keymap_hasu.c $(SRC)
    else 
    	SRC := keymap_hhkb.c $(SRC)
    endif
endif


ifneq (, $(or $(findstring keymap_jp.c, $(SRC)), $(findstring yes, $(HHKB_JP))))
    OPT_DEFS += -DHHKB_JP
endif


# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)


@@ 154,4 151,5 @@ debug-on: EXTRAFLAGS += -DDEBUG -DDEBUG_ACTION
debug-on: all

debug-off: EXTRAFLAGS += -DNO_DEBUG -DNO_PRINT
debug-off: OPT_DEFS := $(filter-out -DCONSOLE_ENABLE,$(OPT_DEFS))
debug-off: all

M keyboard/hhkb/README.md => keyboard/hhkb/README.md +11 -6
@@ 10,11 10,17 @@ See [this thread][AltController] in geekhack.org.
[AltController]: http://geekhack.org/index.php?topic=12047.0


## Update
* Bluetooth module RN-42 is supported.(2015/01)
* V-USB and iWRAP are no longer supported now, but still it'll works with a little fix. See not_supported directory.(2015/01)


##Features
* Customizable keymap
* More keymap layers(more Fn keys)
* Mouse keys
* USB NKRO
* Bluetooth(RN-42)

See README of [tmk_keyboard] for more.



@@ 50,8 56,9 @@ If you use other than **TMK Alt Controller Board** set proper `MCU`, `BOOTLOADER
### Build 
Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. Just `make` with `KEYMAP` option like:

    $ make KEYMAP=[hasu|hhkb|spacefn|<name>]
    $ make -f Makefile.jp KEYMAP=[jp|<name>]        # for HHKB JP
    $ make -f Makefile.<jp|pjrc|rn42> KEYMAP=(hasu|hhkb|spacefn|<name>)

You can omit `-f` option when you use `Makefile`. `Makefile` is used for **Pro2 and Pro**, `Makefile.jp` fits for **JP** model and `Makefile.rn42` supports Bluetooth module **RN-42**. `Makefile.pjrc` uses **PJRC** as output protocol instead of **LUFA**.


### Program


@@ 59,13 66,11 @@ First, push reset button on board to start bootloader.

This command programs the controller with [dfu-programmer] if the tool is installed and configured properly.

    $ make dfu
    $ make -f Makefile.jp dfu       # for HHKB JP
    $ make -f Makefile.<variant> KEYMAP=<name> dfu

Or you can also use [FLIP] command to program. Also the tool should be installed and configured properly. FLIP GUI application is also available.

    $ make flip
    $ make -f Makefile.jp flip      # for HHKB JP
    $ make -f Makefile.<variant> KEYMAP=<name> flip

Use [Teensy Loader] if your controller is Teensy/Teensy++.


R keyboard/hhkb_rn42/config.h => keyboard/hhkb/config_rn42.h +0 -0
M keyboard/hhkb/hhkb_avr.h => keyboard/hhkb/hhkb_avr.h +23 -5
@@ 41,17 41,32 @@ static inline void KEY_UNABLE(void) { (PORTB |=  (1<<6)); }
static inline bool KEY_STATE(void) { return (PIND & (1<<7)); }
static inline void KEY_PREV_ON(void) { (PORTB |=  (1<<7)); }
static inline void KEY_PREV_OFF(void) { (PORTB &= ~(1<<7)); }
#ifdef HHKB_POWER_SAVING
static inline void KEY_POWER_ON(void) {
    DDRB = 0xFF; PORTB = 0x40;          // change pins output
    DDRD |= (1<<4); PORTD |= (1<<4);    // MOS FET switch on
    /* Without this wait you will miss or get false key events. */
    _delay_ms(5);                       // wait for powering up
}
static inline void KEY_POWER_OFF(void) {
    /* input with pull-up consumes less than without it when pin is open. */
    DDRB = 0x00; PORTB = 0xFF;          // change pins input with pull-up
    DDRD |= (1<<4); PORTD &= ~(1<<4);   // MOS FET switch off
}
static inline bool KEY_POWER_STATE(void) { return PORTD & (1<<4); }
#else
static inline void KEY_POWER_ON(void) {}
static inline void KEY_POWER_OFF(void) {}
static inline bool KEY_POWER_STATE(void) { return true; }
#endif
static inline void KEY_INIT(void)
{
    /* row,col,prev: output */
    DDRB  = 0xFF;
    PORTB = 0x00;
    PORTB = 0x40;   // unable
    /* key: input with pull-up */
    DDRD  &= ~0x80;
    PORTD |= 0x80;
    /* keyswitch board power on */
    DDRD  |=  (1<<4);
    PORTD |=  (1<<4);
    PORTD |=  0x80;
#ifdef HHKB_JP
    /* row extention for HHKB JP */
    DDRC  |= (1<<6|1<<7);


@@ 59,6 74,8 @@ static inline void KEY_INIT(void)
#endif
    KEY_UNABLE();
    KEY_PREV_OFF();

    KEY_POWER_OFF();
}
static inline void KEY_SELECT(uint8_t ROW, uint8_t COL)
{


@@ 98,6 115,7 @@ static inline void KEY_SELECT(uint8_t ROW, uint8_t COL)
#define KEY_PREV_OFF()          (PORTE &= ~(1<<7))
#define KEY_POWER_ON()
#define KEY_POWER_OFF()
#define KEY_POWER_STATE()       true


#else

M keyboard/hhkb/keymap_hasu.c => keyboard/hhkb/keymap_hasu.c +18 -16
@@ 27,7 27,7 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
           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,FN6, \
           FN7, Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, FN2, RSFT,FN1, \
                LGUI,LALT,          FN4,                FN5, FN5),
                LGUI,LALT,          FN4,                FN5, RGUI),

    /* Layer 1: HHKB mode[HHKB Fn]
     * ,-----------------------------------------------------------.


@@ 47,7 47,7 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
           CAPS,NO,  NO,  NO,  NO,  NO,  NO,  NO,  PSCR,SLCK,PAUS, UP,  NO,  BSPC, \
           LCTL,VOLD,VOLU,MUTE,NO,  NO,  PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
           LSFT,NO,  NO,  NO,  NO,  NO,  PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
                LGUI,LALT,          SPC,                RALT,RGUI),
                LGUI,LALT,          TRNS,               RALT,RGUI),

    /* Layer 2: Vi mode[Slash]
     * ,-----------------------------------------------------------.


@@ 66,7 66,7 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           TAB, HOME,PGDN,UP,  PGUP,END, HOME,PGDN,PGUP,END, NO,  NO,  NO,  BSPC, \
           LCTL,NO,  LEFT,DOWN,RGHT,NO,  LEFT,DOWN,UP,  RGHT,NO,  NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  NO,  HOME,PGDN,PGUP,END, TRNS,RSFT,NO, \
           LSFT,NO,  NO,  NO,  NO,  NO,  HOME,PGDN,PGUP,END, FN2, RSFT,TRNS, \
                LGUI,LALT,          SPC,                RALT,RGUI),

    /* Layer 3: Mouse mode(IJKL)[Semicolon]


@@ 81,16 81,16 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
     * `-----------------------------------------------------------'
     *      |Gui |Alt  |          Mb1          |Fn   |Fn |
     *      `--------------------------------------------'
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel8
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
     */
    [3] = \
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           FN8, NO,  NO,  NO,  NO,  NO,  WH_L,WH_D,MS_U,WH_U,WH_R,WBAK,WFWD,FN8, \
           LCTL,ACL0,ACL1,ACL2,ACL2,NO,  NO,  MS_L,MS_D,MS_R,TRNS,NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,BTN4,BTN5,NO,  RSFT,NO, \
           FN8, NO,  NO,  NO,  NO,  NO,  NO,  WH_D,MS_U,WH_U,RGHT,FN9, FN10,FN8, \
           LCTL,ACL0,ACL1,ACL2,ACL2,NO,  NO,  MS_L,MS_D,MS_R,FN3, NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,FN9, FN10,NO,  RSFT,TRNS, \
                LGUI,LALT,          BTN1,               TRNS,TRNS),

    /* Layer 5: Mouse mode(IJKL)[Space]
    /* Layer 4: Mouse mode(IJKL)[Space]
     * ,-----------------------------------------------------------.
     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|


@@ 102,13 102,13 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
     * `-----------------------------------------------------------'
     *      |Gui |Alt  |          Mb1          |Fn   |Fn |
     *      `--------------------------------------------'
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel8
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
     */
    [4] = \
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           FN8, NO,  NO,  NO,  NO,  NO,  WH_L,WH_D,MS_U,WH_U,WH_R,WBAK,WFWD,FN8, \
           FN8, NO,  NO,  NO,  NO,  NO,  NO,  WH_D,MS_U,WH_U,RGHT,FN9, FN10,FN8, \
           LCTL,VOLD,VOLU,MUTE,NO,  NO,  NO,  MS_L,MS_D,MS_R,BTN1,NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,BTN4,BTN5,NO,  RSFT,NO, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,FN9, FN10,NO,  RSFT,TRNS, \
                LGUI,LALT,          TRNS,               TRNS,TRNS),

#if 0


@@ 127,9 127,9 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel 
     */
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           TAB, NO,  NO,  NO,  NO,  NO,  WH_L,WH_D,WH_U,WH_R,NO,  NO,  NO,  BSPC, \
           TAB, NO,  NO,  NO,  NO,  NO,  NO,  WH_D,WH_U,RGHT,NO,  NO,  NO,  BSPC, \
           LCTL,NO,  ACL0,ACL1,ACL2,NO,  MS_L,MS_D,MS_U,MS_R,TRNS,QUOT,ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,NO, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,FN9, FN10,SLSH,RSFT,NO, \
                LGUI,LALT,          BTN1,               RALT,TRNS),

    /* Layer4: Mouse mode(HJKL)[Space]


@@ 147,9 147,9 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel 
     */
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           FN8, NO,  NO,  NO,  NO,  NO,  WH_L,WH_D,WH_U,WH_R,NO,  WBAK,WFWD,FN8, \
           FN8, NO,  NO,  NO,  NO,  NO,  NO,  WH_D,WH_U,RGHT,NO,  FN9, FN10,FN8, \
           LCTL,NO,  ACL0,ACL1,ACL2,NO,  MS_L,MS_D,MS_U,MS_R,BTN1,NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,BTN4,BTN5,NO,  RSFT,NO, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,FN9, FN10,NO,  RSFT,NO, \
                LGUI,LALT,          TRNS,               RALT,RGUI),
#endif
#if 0


@@ 201,10 201,12 @@ const uint16_t fn_actions[] PROGMEM = {
    [2] = ACTION_LAYER_TAP_KEY(2, KC_SLASH),          // Cursor layer with Slash*
    [3] = ACTION_LAYER_TAP_KEY(3, KC_SCLN),           // Mousekey layer with Semicolon*
    [4] = ACTION_LAYER_TAP_KEY(4, KC_SPC),            // Mousekey layer with Space
    [5] = ACTION_LAYER_MOMENTARY(3),                  // Mousekey layer
    [5] = ACTION_LAYER_MOMENTARY(4),                  // Mousekey layer(IJKL)
    [6] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_ENT),      // RControl with tap Enter
    [7] = ACTION_MODS_ONESHOT(MOD_LSFT),              // Oneshot Shift
    [8] = ACTION_MACRO(ALT_TAB),                      // Application switching
    [9] = ACTION_MODS_KEY(MOD_LALT, KC_LEFT),
   [10] = ACTION_MODS_KEY(MOD_LALT, KC_RIGHT),

//  [x] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC),        // LControl with tap Backspace
//  [x] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC),         // LControl with tap Esc

M keyboard/hhkb/matrix.c => keyboard/hhkb/matrix.c +25 -2
@@ 27,8 27,15 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#include "timer.h"
#include "matrix.h"
#include "hhkb_avr.h"
#include <avr/wdt.h>
#include "suspend.h"
#include "lufa.h"


// matrix power saving
#define MATRIX_POWER_SAVE       10000
static uint32_t matrix_last_modified = 0;

// matrix state buffer(1:on, 0:off)
static matrix_row_t *matrix;
static matrix_row_t *matrix_prev;


@@ 72,7 79,8 @@ uint8_t matrix_scan(void)
    matrix_prev = matrix;
    matrix = tmp;

    KEY_POWER_ON();
    // power on
    if (!KEY_POWER_STATE()) KEY_POWER_ON();
    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
        for (uint8_t col = 0; col < MATRIX_COLS; col++) {
            KEY_SELECT(row, col);


@@ 126,8 134,16 @@ uint8_t matrix_scan(void)
            // This takes 25us or more to make sure KEY_STATE returns to idle state.
            _delay_us(75);
        }
        if (matrix[row] ^ matrix_prev[row]) matrix_last_modified = timer_read32();
    }
    // power off
    if (KEY_POWER_STATE() &&
            (USB_DeviceState == DEVICE_STATE_Suspended ||
             USB_DeviceState == DEVICE_STATE_Unattached ) &&
            timer_elapsed32(matrix_last_modified) > MATRIX_POWER_SAVE) {
        KEY_POWER_OFF();
        suspend_power_down();
    }
    KEY_POWER_OFF();
    return 1;
}



@@ 165,3 181,10 @@ void matrix_print(void)
        xprintf("%02X: %08b\n", row, bitrev(matrix_get_row(row)));
    }
}

void matrix_power_up(void) {
    KEY_POWER_ON();
}
void matrix_power_down(void) {
    KEY_POWER_OFF();
}

R keyboard/hhkb/Makefile.iwrap => keyboard/hhkb/not_supported/Makefile.iwrap +0 -0
R keyboard/hhkb/Makefile.vusb => keyboard/hhkb/not_supported/Makefile.vusb +0 -0
R keyboard/hhkb/config_iwrap.h => keyboard/hhkb/not_supported/config_iwrap.h +0 -0
R keyboard/hhkb/config_vusb.h => keyboard/hhkb/not_supported/config_vusb.h +0 -0
R keyboard/hhkb/iwrap.txt => keyboard/hhkb/not_supported/iwrap.txt +0 -0
R keyboard/hhkb/usbconfig.h => keyboard/hhkb/not_supported/usbconfig.h +0 -0
R keyboard/hhkb_rn42/rn42.mk => keyboard/hhkb/rn42.mk +0 -0
A keyboard/hhkb/rn42/MEMO.txt => keyboard/hhkb/rn42/MEMO.txt +255 -0
@@ 0,0 1,255 @@
Memo of deveopment
==================
just memo, NOT WORTH READING

Bug:
- Factory Reset PIO4 doesn't work
    - the reason is unclear - 12/08 NOT LOOK INTO ANY MORE
    - WORKAROUND: use serial pins(3.3V, GND, RX and TX)
        - SF,1 and R,1 to set factory defalult
    

Todo:
- LED cover and switch knob and new Slide Switch
- RN42 auto configuration
    - configure the module as HID device every time powering up
    - this'll reduce work load of assembly

- move rn42 to protocol directory when it becomes reusable stack

- sendchar() in lufa.c no buffer
    - no buffering. character lost can be caused.
- LUFA sendchar should be buffered and serial_uart.c buffur size is too large(256).

- BT operations
    - disconnect
    - new connection
    - remove connection

- sendchar() in lufa.c block loop   - DONE 11/29
    - block loop when powered with AC adapter
    - FrameNumber is not updated when adapter powered

Improving:
- ADC resolution
    AVR120
    AVR32138
    - Enhancing ADC resolution by oversampling
        AVR121  http://www.atmel.com/images/doc8003.pdf
    - disable digital input buffer DIDR(7.8.6)

Design:
- suspend.h - DONE 11/26
    - remove argument from suspend_power_down() for backward compatitibility
- remove MCU dependent power saving code from core/keyboard - DONE 11/23
    - it should be located in project matrix.c
- HHKB matrix.c needs matrix_prev?
    - is_modified() is obsolete now. really needs?
- ADC: removing AREF capacitor C10
    - seems to be better while usb powered
    - still bad while battery powered
    http://electronics.stackexchange.com/questions/105849/avcc-and-capacitor-using-adc
- ADC: smaller resistors for voltage dividor
    - 1K + 1K: not improved. - 11/27


LUFA:
USB connection check: state of USB deivce
- USB_DeviceState:
    USB_Deivce_State_t { Unattached, Powered, Default, Addressed, Configured*, Suspended* }
    Unattached: unpluged
    Powered:    pluged with power adapter
    Default:    enumerate process bigin
    Addressed:  addressed
    Configured: enumerated
    Suspended:  suspended

- USB_IsInitialized: state of LUFA core setup
    becomes true in USB_Init()  USBController_AVR8.c
    becomes false in USB_Disable()  USBController_AVR8.c
- USB_VBUS_GetStatus(): state of VBUS(power/connection)
- USB_Disable() detaches, disables all interrupts, controller, PLL, regulater.

- When connect to power adapter
    - event happened: CW or CSW or C or DDC
    - USB state: not configured

- USB evnets
    - USB connect: CSWRWRW
    - USB connect but fail to enumeration: CWRWRWRWS
    - USB disconnect: D
    - Power adapter connect: CW, CSW, C
    - Power adapter disconnect: D


Power saving:
- Pro2 current consumption
    - active: 138.2mA(no device on Hub)
    - suspended: 30.9mA(WakeUp enabled DIPSW6)
    - suspended: 0mA->46.0mA(WakeUp disabled DIPSW6)
- Pro current consumption
    - active: 54.0mA
    - suspended: 40.5mA(WakeUp enabled DIPSW6)
    - suspended: 0.3mA(WakeUp disabled DIPSW6)

- RN42 3.3V
    - disconnected(Idle): 5mA (config mode)
    - connected(Active):
        SW,0000:  23-26mA
        SW,0010:  27-29mA worse than 0000 for unknown reason
        SW,0020:  17-19mA mouse NG
        SW,0030:  13-16mA laggy mouse NG
        SW,0050:  10-13mA laggy mouse NG

- matrix power saving
    - power saving while externally powered and not while unpluged
- confirm suspend mode lufa.c: matrix_power_*, suspend_wakeup_condition
- 8MHz clock
- When not connected in a few minutes get into deep sleep to save battery life
- CTS is needed for waking up from deep sleep? How deep sleep is activated?
- firmware controlled 3.3V DC converter to switch on/off BT module
- sleep MCU and BT module(keyboard is not used)
- deep sleep MCU and BT module(keyboard is not used for long time)
- deep sleep MCU and turn off BT module(keyboard is not used and not connected)
- Battery ADC; switching, high resistance
    - switching gnd end of divider with PF4
    - high resistor 100K/1M?
        capacitor   10nF
        http://www.eevblog.com/forum/beginners/measuring-battery-voltage-without-consuming-current/
- During USB suspend change clock source to internal RC from external Xtal(6.8)
- FRZCLK: you can freeze clock for power saving. still WAKEUPI and VBUSTI interrupts are available while freezing.(21.7.3)
- Suspend: Clear Suspend Bit, Freeze clock, disable PLL, MCU sleep(21.13)
- Voltage reference(8.1.1)
    - to reduce power consumption while power down mode
- unset ADEN before sleep(24.7)







Lipo
----
850mA lasts around 9 hours(07/28)

Sparkfun Polymer Lithium Ion Battery 850mAh:
https://www.sparkfun.com/products/341
Lipo Cell spec:
https://www.sparkfun.com/datasheets/Batteries/063048%20Li-polymer.pdf
Protection spec:
http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Prototyping/BatteryProtection.pdf
                                min     typical max
    over-charge                 4.255   4.280   4.305
    over-charge discover?       4.030   4.080   4.130
    over-discharge              2.827   2.900   2.973
    over-discharge discover     3.022   3.100   3.178

ADC voltage monitor:    voltage divider 10K+10K(0.5)
                        ADC=V*0.5/2.56*1024

    V       ADC
    ------------------
    4.20    0x347(839)
    3.10    0x26b(619)




TROUBLE SHOOT
-------------
07/16   After fix of voltage dividor on GPIO6, had a trouble that it could not send a char to BT module, though could receive.
        Found R8 had wrong 1K resistor and changed to 10K, after that it can send to the module again. Not sure how it had sent with the wrong 1K before.

07/18   On Linux, had an USB related trouble; keyboard or console didn't work for some reason. Changing PID cured this problem. Very annoying, took very long time before resolved it.

12/07   rn42_rts() read 1 every time. R12 broke in open mode(no coductive), idk why, too much heat with soldering? and PF1 pin was not soldered.
        It resolved with resoldering PF1 and new resistor on R12.




Done:
- low battery alert(solid light) 09/04
- *** Rev.E BT test *** - DONE
    - with MCP73832, new Schottky, tantalum caps - DONE 12/07
        * MCP73832 doesn't leak from Vcc pin when unpluged and battery powered
            34mV vs 2.07V(MCP73831) at Vcc pin
            MCP73832 doesn't need revese protection diode D5
        * PMEG2010ER is very low VF while reverse current/voltage is high
            VF=0.96 vs 1.98(RB160M-30TR)with Fluke 175
            Anode of D11 is 680mV vs 20mV(RB160M-30TR)
            780mV is still low < 1.4V VBUS plugin detection(21.11)
                this doesn't cause false VBUS detect
                and 780mV on MCP73832 Vcc pin is also no problem.
            D5 can be removed.
    - ADC divider switching - DONE 12/07
        * Drain and Source of Q4 Pch was reversed wrongly on Rev.E.

    - reverse current from Lipo charger - DONE 12/07
        * MCP73832 has no recverse current from Vcc pin unlike MCP73831


- Rev.F design - DONE
    - current measure point - DONE 12/08
    - change value of cap 68->47    - DONE 12/08
    - PPTC land pattern: no solder jumper, use 0Ohm resistor instead - CANCEL 12/08
    - Q4 Pch FET: wrong Drain and Source - DONE 12/08
    - D5 can be removed.    - DONE 12/08



- BT_INDICATOR LED turns on wrongly when touching line or pin.  -- pull-up enabled on PF6/GPIO2 08/30
- Lipo charger configuration: fast charge time:  USB charger spec? -- used 2kohm
- use LED of charger to alarm low battery. LED should be powered directly from Lipo? - cancel; powered from VUSB
- Use RTS in serial_uart.c to resolve missing chars from help message of RN-42 - done
- CTS/RTS lines are needed? just connect in loop back if no flow control is needed. - done
- add IO pin to charger status CHRG; LED control(low) and detect charge status(input HiZ) 07.24
- LINKED: add trace on PIO2 to PF6   07.24
- Lipo voltage ADC sensing
- Lipo charger MCP73831: needs capacitor 4.7uF *2
- USB connection check - 07.01
- BT on/off check: whether RX line is pulled up? - checking RTS 07.01
- USB/BT switching  BT is on -> BT, BT is off -> USB - 07.01
- Under voltage lock out UVLO for protection of Lipo - Lipo has discharge protection at 3.100V    07.01
- Power saving: HHKB scan, BT radio control - 9h with 850mAh, this is enough   07.01
- Power selector doesn't work; Q4 MOSFET leaks from Lipo to USB power line. -- use Schottky instead 07/04

- wrongly suspended when powered from adapter without USB connection - DONE
    - suspend event may occur when plug into adapter
    - and never wake until conected to real USB line
    - without debug print via USB no problem; CSW(wake just after suspend as real USB line)
    - seems like USB print causes this problem after suspended

- lose USB connection during power-down mode - DONE
    - USB initialize code in main() causes this - WRONG
    - Do not power-down during USB connection is active - DONE 11/11
        (USB_DeviceState == USB_DEVICE_Configured) is used to check USB connection
        matrix_power_down() matrix.c - 11/23

- with Nexus5 keyboard and mouse are very laggy.
    Not confirmed. 01/15

- switch BT host connections    - CANCEL 01/15
    - switch next connection
        cannot switch connection with version 6.15 at least

- When given power only from wall wart adapter  - DONE? not confirmed 01/15
    - it sleeps. it should not sleep
    - Configured state without USB connection?

- timer is slow while power down - DONE 11/26
    - time out interrupt is lost while power down?
    - interrupt of watchdog timer compensates timer counter(avr/suspend.c)

- repeated CHARGING/FULL_CHARGED    - No longer problem 01/15
    - In LTC sharp pulses are observed.
    - MCP has no pulse but still has a problem.
    - needs more wait before read pin state? - NO

- USB plug-in fails while BT        - No longer problem 01/15
    - it ends in suspend state
    - maybe, not responsive to host enumeration process due to power-down.
    - matrix_power_down() only when state is unattached - 11/26
        - need to observe a while


R keyboard/hhkb_rn42/PowerSave.txt => keyboard/hhkb/rn42/PowerSave.txt +25 -39
@@ 1,5 1,28 @@
RN-42
=====
Power Saving
============


MCU+HHKB Power Comsumption
--------------------------
Battery drive:
    idle    18.9mA
    active  35.8mA

USB powered:
    40.0mA
    52mA    01/17

Other keyboards:
HHKB Pro    55mA
HHKB Pro2   140mA
HHKB Pro    42mA(Alt)
HHKB Pro2   52mA(Alt BT controller USB mode)
HHKB Pro2   88mA(Alt BT controller BT mode connected)
HHKB Pro2   68mA(Alt BT controller BT mode config mode)
Poker X     6mA
Infinity    24mA(TMK)
            65mA(kiibohd)


HHKB key switch power control
-----------------------------


@@ 63,40 86,3 @@ S%,1000         status led and connection control don't work
                GPIO5: status LED
                GPIO6: Connection control
                GPIO2: linked status





Ver 6.15 04/26/2013
(c) Roving Networks
***Settings***
BTA=00066667BBE9
BTName=tmkBT-BBE9
Baudrt(SW4)=115K
Mode  =DTR
Authen=1
Bonded=0
Rem=001BDC06415B
***ADVANCED Settings***
SrvName= keyboard/mouse
SrvClass=0000
DevClass=1F00
InqWindw=0012
PagWindw=0012
CfgTimer=255
StatuStr=NULL
HidFlags=3c
DTRtimer=8
KeySwapr=0
***OTHER Settings***
Profile= HID
CfgChar= $
SniffEna=8010
LowPower=0          S|,
TX Power=fff4       SY,
IOPorts= 0
IOValues=0
Sleeptmr=0
DebugMod=0
RoleSwch=0

A keyboard/hhkb/rn42/RN42.txt => keyboard/hhkb/rn42/RN42.txt +408 -0
@@ 0,0 1,408 @@
RN-42 Bluetooth Module Support
==============================
Bluetooth controller board works with HHKB Pro2, JP, Type-S and Type-S JP and it supports both USB and Bluetooth as keyboard output protocol. Bluetooth module Roving Networks/Microchip RN-42 is installed on the board.


RN-42:
http://www.microchip.com/wwwproducts/Devices.aspx?product=RN42


Capabitlities:
- USB keyboard functions
    completely equivarent to USB controller including mouse keys and NKRO.
- Switching between USB and Bluetooth
    You can switch the two connections with BT switch or key combination.
- RN-42 config mode
    You can change power/connection configuration of the module if needed.
- Low battery alert
    Red LED turns on when low voltage.
- RN-42 status indicator
    LED indicates status of Bluetooth connection.
- Pairing
    The module stores up to 8 connections.
- Auto connect
    The module connects the last connected device automatically.
- iOS support
    works as keyboard with iPhone5. No tested completely.
- Android support
    works as keyboard and mouse with Nexus5. No tested completely.
- Mouse keys over BT
    Note that iOS doesn't accept mouse device.


Limitations:
- Short battery life
    Around 12hr with 1000mAh
- No connection switching
    RN-42 auto-connects to the last connected device.
    Some of consumer products can switch between devices, for example Logitech K480.
        http://www.logitech.com/en-us/product/multi-device-keyboard-k480?crid=26
- HHKB JP requires case modification for BT switch and LEDs.
    without switch power controlled by MCU? Probably using 3.3V regulator enable pin power of RN-42 can be controlled.

NOTE:
- LIPO BATTERY IS VERY DANGEROUS, TAKE EXTRA CARE OF YOUR SAFETY AND PROPERTY.
- RN-42 version 6.15 is supported.
- No NKRO over Bluetooth
- Check you country's wiress regulation and certification of RN-42.

Bugs:

Todos:


Lipo Battery
------------
You can use 3.7V Lithium Ion battery with JST PH 2pin connector and protection circuit.
Battery space inside HHKB is around 54mm x 50mm and its height is 7mm.

Sparkfun 850mAh
https://www.sparkfun.com/products/341
Sparkfun 1000mAh
https://www.sparkfun.com/products/339

Sparkfun 2000mAh battery won't fit due to its size.

Learn about Lipo battery:
https://learn.adafruit.com/li-ion-and-lipoly-batteries





LED Status
----------
Configuring                     10 times per sec
Startup/configuration timer     2 times per sec
Discoverable/Inquiring/Idle     once per sec
Connected                       solid on


RN-42 Magic Command
--------------------
Magic key combination is 'LShift+RShift' by default in case of HHKB.

Here is help.

    ----- Bluetooth RN-42 Help -----
    i:       RN-42 info
    b:       battery voltage
    Del:     enter/exit RN-42 config mode
    Slck:    RN-42 initialize
    p:       pairing
    u:       toggle Force USB mode

    RN-42 info:             displays information of the module on console.
    battery voltage:        displays current voltage of battery and uptime.
    RN-42 initialize:       does factory reset and configures RN-42
    pairing:                enters Pairing mode.
    toggle Force USB mode:  switch between USB and Bluetooth


RN-42 Config mode
-----------------
You can tune/operate RN-42 yourself with config(command) mode.

1. hook up USB cable
2. run `hid_listen` command  in console
3. turn on Bluetooth switch
4. press LShift+RShift+Delete(Fn+~) you will see output like followings:

    Entering config mode ...
    CMD
    v
    Ver 6.15 04/26/2013
    (c) Roving Networks

5. do config with RN-42 commands. See documentations of RN-42.
6. to exit also press LShift+RShift+Delete(Fn+~)

    Exiting config mode ...
    ---
    END


RN-42 Initial Configuration
---------------------------
RN-42 is configured as SPP device at factory reset, you need to configure it as HID device. This is needed just once first time.

1. hook up USB cable
2. run `hid_listen` command  in console
3. turn on Bluetooth switch
4. press LShift+RShift+ScrLk(Fn+O) you will see output like followings:

    Entering config mode ...
    CMD
    Ver 6.15 04/26/2013
    (c) Roving Networks
    ECHO ON
    SF,1
    AOK
    S-,TmkBT
    AOK
    SS,Keyboard/Mouse
    AOK
    SM,4
    AOK
    SW,8000
    AOK
    S~,6
    AOK
    SH,003C
    AOK
    SY,FFF4
    AOK
    R,1
    Reboot!
    Exiting config mode ...

5. output of command 'X' after cofiguration

    Ver 6.15 04/26/2013
    (c) Roving Networks
    ***Settings***
    BTA=00066667BBE9
    BTName=TmkBT-BBE9
    Baudrt(SW4)=115K
    Mode  =DTR 
    Authen=1
    PinCod=1234
    Bonded=0
    Rem=NONE SET
    ***ADVANCED Settings***
    SrvName= Keyboard/Mouse
    SrvClass=0000
    DevClass=1F00
    InqWindw=0100
    PagWindw=0100
    CfgTimer=255
    StatuStr=NULL
    HidFlags=3c
    DTRtimer=8
    KeySwapr=0
    ***OTHER Settings***
    Profile= HID
    CfgChar= $
    SniffEna=8000
    LowPower=0
    TX Power=fff4
    IOPorts= 0
    IOValues=0
    Sleeptmr=0
    DebugMod=0
    RoleSwch=0


Switch to USB mode
------------------
You can switch between USB and Bluetooth with pressing 'LShift+RShift+u'.


Pairing mode
------------
This disconnects current connect and enter pairing mode.




For deveropment
===============

RN-42 Serial Connection
-----------------------
UART:           115200bps, 8bit, 1-stopbit, non-parity, no flow control
SSP:            115200bps, 8bit, 1-stopbit, non-parity, no flow control(via Bluetooth)

To enter command mode disconnect the module from host and type '$$$'.(you will see 'CMD') and type '+' to get local echo. To exit type '---'(you will see 'END').


RN-42 Commands
--------------
S-,tmkBT            // Device name
SS,keyboard/mouse   // service name
SM,4                // Auto Connect DTR mode
SW,8010             // Sniff enable 0x10*0.625ms=10ms; 50ms is laggish and not much power save
S~,6                // HID profile
S~,0                // SPP profile
SH,003C             // HID register
SY,0004             // Transmit power
SC,0000             // COD: 000005C0    (see HID spec/Bluegiga doc)
SD,05C0             //     bit 12-8         7           6           5-0
                    //         00101        1           1           0
                    //         peripheral   pointing    keybaord    joystick, gamepad, ...
SM,6                // Pairing mode: auto connect
SM,4                // Master mode: Connection can be controled with GPIO6
SF,1                // Factroy reset
R,1                 // reboot
SR,Z                // removes all remote addresses for reconnecting.
                    // can be used to connect another host
SR,I                // registers last inquiry address


Operation Modes
---------------
SM,3        Auto Connect Master mode
SM,4        Auto Connect DTR Mode uses GPIO6 to make and break connection(Mode =DTR)
                confirm: auto connect works and control connection with GPIO6
SM,5        Auto Connect ANY Mode (Mode =ANY)
                each time GPIO is set, make inquiry and connect to the first found device
SM,6        automatically reconnect(Mode =Pair)
                confirm: auto connect works well but difficult to enter command mode.


HID flag register
-----------------
SH,0200
GH

10 0000 0000(0200)  default
00 0011 1000(0038)  Combo
|| |  | |\_\____ number of paired devices to which the module can reconnect
|| |  | \_______ send out reports over UART (0xFF <len> <data>)
|| \__\_________ descriptor type
|\______________ toggle virtual keyboard on iOS when first connected
\_______________ Force HID mode if GPIO11 is high on power-up

    Descriptor type:
    0000:   keybaord
    0001:   Game Pad
    0010:   Mouse
    0011:   Combo
    0100:   Joystick
    1xxx:   reserved


Out report - Indicator
----------------------
0xFE 0x02 0x01 <LED_state>


Apple iOS
---------
Keyboard can be used with iPhone, but mouse cannot.


Android
-------
3.7.1.5 Note: To connect with Android phone the modules must wake up 11ms every 2.5seconds.


Power Management
----------------
Inquiry and Page window     Idle or Active  (3.1.1)
    Downside: delay in discovery or connection time
    SI,         // set inquiry scan window(discovery) on/off duty?
    SJ,         // set page scan window(connection)
    This reduces averaege power >20mA to 5mA(3mA in Sniff mode)

Sniff mode                  Transmit
    Sniff mode is disabled by default and radio is active continuously when connected.(25-30mA)
    In Sniff mode the radio wakes up intermittently and sleeps in very low power mode.(2mA)
    SW,<val>    // set interval timer(*0.625ms) 0000-7FFF

Deep sleep                  Idle            (3.1.2)
    In this mode the module shuts down completly and only draws about 300uA. To enable this set the most signifant bit(0x8000) of Sniff interaval timer.
    SW,8320     // deep sleep enable(interval=0x320*0.625=500ms)
    In normal sleep the firmware is still running in idle mode, and wakes up about 20 times per second to check ports, update LEDs, etc. During deep sleep, the firmware actually stops runnig some tasks and the LEDs only update about once per second.
    To wake from deep sleep there are three ways: (in worst case wake up takes 5ms)
        *send a charactor to the UART(first charactor will be lost)
        *toggle CTS low to high and wait 5ms
        *wake automatically every slot time(<val>*0.625ms)
    Once the radio is awake it stay active for exactly 1 second of inactivity and then sleeps again.
    Downside: latency and data loss

Disable Output driver       Idle or Active  (3.1.3)
    S%,1000     // set all GPIO pins(0-11) to inputs.

Lower Transmit Power        Idle or Active  (3.1.4)
    SY,<hex>    // transmit power setting(takes effect after a power cycle and reboot)
    Downside: reducing effective range


Optimizig for Latency
---------------------
By default the firmware is optimized for throughput.
SQ,16           // set latency bit
SQ,0            // unset latency bit


Configuration timer settings
----------------------------
Remote configuration is used for the module to be configured with various commands over Bluetooth(SPP profile only?).

The module has remote configuration timer to allow remote configuration over Bluetooth after power up in Slave mode. In Master modes the remote configuration timer is set to 0(no remote configuration). (In Trigger Master mode the timer is used as an idle timer to break the connection after time expires with no charactors receive.)
    ST,0        // no remote, no local when connected
    ST,<1-252>  // local and remote with timeout in seconds from power up
    ST,253      // local only       without timeout
    ST,254      // remote only      without timeout
    ST,255      // local and remote without timeout


Commands
--------
S7,                     7bit mode
SA,                     Authenticaiton
SB,                     Send break
SC,                     Service class
SD,                     Device class
SM,<val>                Operation mode
SP,<string>             Pin code(alpahnumeric)
SQ,<mask>               Special configuration(GPIO, discovery mode, low latency, reboot, UART)
SR,<hex>                Store remote address
SR,Z                    Erase all address
SS,<string>             Set service name(1-20)**
ST,<val>                Remote configuration timer(Master:0, Slave:0-255, Triger:as idle timer)
SU,<val>                UART baud rate
SW,<val>                low-power sniff mode** deep sleep and wake up every 625us * <val>
SX,<0|1>                bonding enable  only acceps device that matches the stored address
SY,<hex>                power setting**
SZ,<val>                non-standard raw baud rate  <val>=baud*0.004096
S~,<val>                Profile     0:SPP, 5:APL, 6:HID
S-,<string>             Device name     -15 alphanumeric charactors
S?,<0|1>                role switch enable
S$,<char>               command mode char
$|,<hex>                low-power connect mode  deep sleep/active(discoverable and connectable) cycle
D                       display basic setting
E                       display extended setting
GB                      display the device's Bluetooth address
GF                      display Bluetooth address of connected device
GK                      show connection status
GR                      show remote address for reconnecting
G&                      show GPIO pin
G<char>                 show stored setting
+                       toggle local echo on/off
&                       show GPIO 3,4,6,7(DIP switch)
C                       connect to stored remote address
C,<address>             connect last address
CFI                     connect and go into fast data mode
CFR                     connect and go into fast data mode
CT,<address>,<val>      connect to the address and disconnect after val?
F,1                     fast data mod:
H                       display help
I,<time>,<cod>          inquiry scan with <cod>
IN,<time>,<cod>         inquiry scan with <cod>, return without BT name
IR                      inquiry scan with 0055AA
IS                      inquiry scan with 001F00
J                       hide pin code
K,                      kill    disconnects current connection
L                       link quality
M                       show modem signlal status
O                       display other settings
P,<char>                pass through?
Q                       quiet mode  make the module not discoverable
Q,0                     discoverable and connectable
Q,1                     not discoverable and not connectable
Q,2                     not discoverable and connectable
Q,?                     display current quiet mode
R,1                     reboot
T,<0|1>                 pass received data while in command mode
U,<baud>,<parity>       change UART setting tentatively
V                       display firmware version
W                       wake from quiet mode    enable discovery and connection
Z                       deep sleep mode(<2mA)


Reset to Factory Default
------------------------
SF,1
R,1

R keyboard/hhkb_rn42/rn42/battery.c => keyboard/hhkb/rn42/battery.c +7 -13
@@ 20,7 20,10 @@ void battery_init(void)
    // Ref:2.56V band-gap, Input:ADC0(PF0), Prescale:128(16MHz/128=125KHz)
    ADMUX = (1<<REFS1) | (1<<REFS0);
    ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
    ADCSRA |= (1<<ADEN);
    // digital input buffer disable(24.9.5)
    DIDR0 = (1<<ADC0D) | (1<<ADC4D) | (1<<ADC7D);
    DIDR1 = (1<<AIN0D);
    DIDR2 = (1<<ADC8D) | (1<<ADC9D) | (1<<ADC11D) | (1<<ADC12D) | (1<<ADC13D);

    // ADC disable voltate divider(PF4)
    DDRF  |=  (1<<4);


@@ 88,23 91,14 @@ uint16_t battery_voltage(void)
    PORTF |=  (1<<4);

    volatile uint16_t bat;
    //ADCSRA |= (1<<ADEN);

    // discard first result
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC)) ;
    bat = ADC;

    // discard second result
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC)) ;
    bat = ADC;
    ADCSRA |= (1<<ADEN);
    _delay_ms(1);   // wait for charging S/H capacitance

    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC)) ;
    bat = ADC;

    //ADCSRA &= ~(1<<ADEN);
    ADCSRA &= ~(1<<ADEN);

    // ADC disable voltate divider(PF4)
    DDRF  |=  (1<<4);

R keyboard/hhkb_rn42/rn42/battery.h => keyboard/hhkb/rn42/battery.h +0 -0
R keyboard/hhkb_rn42/rn42/main.c => keyboard/hhkb/rn42/main.c +14 -5
@@ 17,8 17,8 @@

static int8_t sendchar_func(uint8_t c)
{
    sendchar(c);    // LUFA
    xmit(c);        // SUART
    sendchar(c);    // LUFA
    return 0;
}



@@ 63,7 63,7 @@ int main(void)
        USB_USBTask();
#endif
    }
    print("USB configured.\n");
    print("\nUSB init\n");

    rn42_init();
    rn42_task_init();


@@ 82,10 82,19 @@ int main(void)
    sleep_led_init();
#endif

    print("Keyboard start.\n");
    print("Keyboard start\n");
    while (1) {
        while (USB_DeviceState == DEVICE_STATE_Suspended) {
            suspend_power_down(WDTO_120MS);
        while (rn42_rts() && // RN42 is off
                USB_DeviceState == DEVICE_STATE_Suspended) {
            print("[s]");
            matrix_power_down();
            suspend_power_down();
            suspend_power_down();
            suspend_power_down();
            suspend_power_down();
            suspend_power_down();
            suspend_power_down();
            suspend_power_down();
            if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
                    USB_Device_SendRemoteWakeup();
            }

R keyboard/hhkb_rn42/rn42/rn42.c => keyboard/hhkb/rn42/rn42.c +30 -1
@@ 4,6 4,7 @@
#include "serial.h"
#include "rn42.h"
#include "print.h"
#include "timer.h"
#include "wait.h"




@@ 47,11 48,39 @@ void rn42_init(void)
    serial_init();
}

int16_t rn42_getc(void)
{
    return serial_recv2();
}

const char *rn42_gets(uint16_t timeout)
{
    static char s[24];
    uint16_t t = timer_read();
    uint8_t i = 0;
    int16_t c;
    while (i < 23 && timer_elapsed(t) < timeout) {
        if ((c = rn42_getc()) != -1) {
            if ((char)c == '\r') continue;
            if ((char)c == '\n') break;
            s[i++] = c;
        }
    }
    s[i] = '\0';
    return s;
}

void rn42_putc(uint8_t c)
{
    serial_send(c);
}

void rn42_puts(char *s)
{
    while (*s)
	serial_send(*s++);
}

bool rn42_autoconnecting(void)
{
    // GPIO6 for control connection(high: auto connect, low: disconnect)


@@ 97,7 126,7 @@ bool rn42_linked(void)
    //   Hi-Z:  Not powered
    //   High:  Linked
    //   Low:   Connecting
    return !rn42_rts() && PINF&(1<<6);
    return PINF&(1<<6);
}



R keyboard/hhkb_rn42/rn42/rn42.h => keyboard/hhkb/rn42/rn42.h +3 -0
@@ 7,7 7,10 @@ host_driver_t rn42_driver;
host_driver_t rn42_config_driver;

void rn42_init(void);
int16_t rn42_getc(void);
const char *rn42_gets(uint16_t timeout);
void rn42_putc(uint8_t c);
void rn42_puts(char *s);
bool rn42_autoconnecting(void);
void rn42_autoconnect(void);
void rn42_disconnect(void);

R keyboard/hhkb_rn42/rn42/rn42_task.c => keyboard/hhkb/rn42/rn42_task.c +279 -95
@@ 1,4 1,7 @@
#include <stdint.h>
#include <string.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "keycode.h"
#include "serial.h"
#include "host.h"


@@ 9,6 12,7 @@
#include "print.h"
#include "debug.h"
#include "timer.h"
#include "wait.h"
#include "command.h"
#include "battery.h"



@@ 34,39 38,34 @@ void rn42_task_init(void)
void rn42_task(void)
{
    int16_t c;
    if (config_mode) {
        // Config mode: print output from RN-42
        while ((c = serial_recv2()) != -1) {
            // without flow control it'll fail to receive data when flooded
            xprintf("%c", c);
        }
    } else {
        // Raw mode: interpret output report of LED state
        while ((c = serial_recv2()) != -1) {
            // LED Out report: 0xFE, 0x02, 0x01, <leds>
            // To get the report over UART set bit3 with SH, command.
            static enum {LED_INIT, LED_FE, LED_02, LED_01} state = LED_INIT;
            switch (state) {
                case LED_INIT:
                    if (c == 0xFE) state = LED_FE;
                    else           state = LED_INIT;
                    break;
                case LED_FE:
                    if (c == 0x02) state = LED_02;
                    else           state = LED_INIT;
                    break;
                case LED_02:
                    if (c == 0x01) state = LED_01;
                    else           state = LED_INIT;
                    break;
                case LED_01:
                    dprintf("LED status: %02X\n", c);
                    rn42_set_leds(c);
                    state = LED_INIT;
                    break;
                default:
                    state = LED_INIT;
            }
    // Raw mode: interpret output report of LED state
    while ((c = rn42_getc()) != -1) {
        // LED Out report: 0xFE, 0x02, 0x01, <leds>
        // To get the report over UART set bit3 with SH, command.
        static enum {LED_INIT, LED_FE, LED_02, LED_01} state = LED_INIT;
        switch (state) {
            case LED_INIT:
                if (c == 0xFE) state = LED_FE;
                else {
                    if (0x0 <= c && c <= 0x7f) xprintf("%c", c);
                    else xprintf(" %02X", c);
                }
                break;
            case LED_FE:
                if (c == 0x02) state = LED_02;
                else           state = LED_INIT;
                break;
            case LED_02:
                if (c == 0x01) state = LED_01;
                else           state = LED_INIT;
                break;
            case LED_01:
                dprintf("LED status: %02X\n", c);
                rn42_set_leds(c);
                state = LED_INIT;
                break;
            default:
                state = LED_INIT;
        }
    }



@@ 96,18 95,6 @@ void rn42_task(void)
            battery_led(LED_CHARGER);
        }

        static uint8_t prev_status = UNKNOWN;
        if (bs != prev_status) {
            prev_status = bs;
            switch (bs) {
                case FULL_CHARGED:  xprintf("FULL_CHARGED\n"); break;
                case CHARGING:      xprintf("CHARGING\n"); break;
                case DISCHARGING:   xprintf("DISCHARGING\n"); break;
                case LOW_VOLTAGE:   xprintf("LOW_VOLTAGE\n"); break;
                default:            xprintf("UNKNOWN STATUS\n"); break;
            };
        }

        /* every minute */
        uint32_t t = timer_read32()/1000;
        if (t%60 == 0) {


@@ 115,7 102,7 @@ void rn42_task(void)
            uint8_t h = t/3600;
            uint8_t m = t%3600/60;
            uint8_t s = t%60;
            xprintf("%02u:%02u:%02u\t%umV\n", h, m, s, v);
            dprintf("%02u:%02u:%02u\t%umV\n", h, m, s, v);
            /* TODO: xprintf doesn't work for this.
            xprintf("%02u:%02u:%02u\t%umV\n", (t/3600), (t%3600/60), (t%60), v);
            */


@@ 124,7 111,7 @@ void rn42_task(void)


    /* Connection monitor */
    if (rn42_linked()) {
    if (!rn42_rts() && rn42_linked()) {
        status_led(true);
    } else {
        status_led(false);


@@ 136,70 123,238 @@ void rn42_task(void)
/******************************************************************************
 * Command
 ******************************************************************************/
static host_driver_t *prev_driver = &rn42_driver;

static void print_rn42(void)
{
    int16_t c;
    while ((c = rn42_getc()) != -1) {
        xprintf("%c", c);
    }
}

static void clear_rn42(void)
{
    while (rn42_getc() != -1) ;
}

#define SEND_STR(str)       send_str(PSTR(str))
#define SEND_COMMAND(cmd)   send_command(PSTR(cmd))

static void send_str(const char *str)
{
    uint8_t c;
    while ((c = pgm_read_byte(str++)))
        rn42_putc(c);
}

static const char *send_command(const char *cmd)
{
    static const char *s;
    send_str(cmd);
    wait_ms(500);
    s = rn42_gets(100);
    xprintf("%s\r\n", s);
    print_rn42();
    return s;
}

static void enter_command_mode(void)
{
    prev_driver = host_get_driver();
    clear_keyboard();
    host_set_driver(&rn42_config_driver);   // null driver; not to send a key to host
    rn42_disconnect();
    while (rn42_linked()) ;

    print("Entering config mode ...\n");
    wait_ms(1100);          // need 1 sec
    SEND_COMMAND("$$$");
    wait_ms(600);           // need 1 sec
    print_rn42();
    const char *s = SEND_COMMAND("v\r\n");
    if (strncmp("v", s, 1) != 0) SEND_COMMAND("+\r\n"); // local echo on
}

static void exit_command_mode(void)
{
    print("Exiting config mode ...\n");
    SEND_COMMAND("---\r\n");    // exit

    rn42_autoconnect();
    clear_keyboard();
    host_set_driver(prev_driver);
}

static void init_rn42(void)
{
    // RN-42 configure
    if (!config_mode) enter_command_mode();
    SEND_COMMAND("SF,1\r\n");  // factory defaults
    SEND_COMMAND("S-,TmkBT\r\n");
    SEND_COMMAND("SS,Keyboard/Mouse\r\n");
    SEND_COMMAND("SM,4\r\n");  // auto connect(DTR)
    SEND_COMMAND("SW,8000\r\n");   // Sniff disable
    SEND_COMMAND("S~,6\r\n");   // HID profile
    SEND_COMMAND("SH,003C\r\n");   // combo device, out-report, 4-reconnect
    SEND_COMMAND("SY,FFF4\r\n");   // transmit power -12
    SEND_COMMAND("R,1\r\n");
    if (!config_mode) exit_command_mode();
}

#if 0
// Switching connections
// NOTE: Remote Address doesn't work in the way manual says.
// EEPROM address for link store
#define RN42_LINK0  (uint8_t *)128
#define RN42_LINK1  (uint8_t *)140
#define RN42_LINK2  (uint8_t *)152
#define RN42_LINK3  (uint8_t *)164
static void store_link(uint8_t *eeaddr)
{
    enter_command_mode();
    SEND_STR("GR\r\n"); // remote address
    const char *s = rn42_gets(500);
    if (strcmp("GR", s) == 0) s = rn42_gets(500);   // ignore local echo
    xprintf("%s(%d)\r\n", s, strlen(s));
    if (strlen(s) == 12) {
        for (int i = 0; i < 12; i++) {
            eeprom_write_byte(eeaddr+i, *(s+i));
            dprintf("%c ", *(s+i));
        }
        dprint("\r\n");
    }
    exit_command_mode();
}

static void restore_link(const uint8_t *eeaddr)
{
    enter_command_mode();
    SEND_COMMAND("SR,Z\r\n");   // remove remote address
    SEND_STR("SR,");            // set remote address from EEPROM
    for (int i = 0; i < 12; i++) {
        uint8_t c = eeprom_read_byte(eeaddr+i);
        rn42_putc(c);
        dprintf("%c ", c);
    }
    dprintf("\r\n");
    SEND_COMMAND("\r\n");
    SEND_COMMAND("R,1\r\n");    // reboot
    exit_command_mode();
}

static const char *get_link(uint8_t * eeaddr)
{
    static char s[13];
    for (int i = 0; i < 12; i++) {
        uint8_t c = eeprom_read_byte(eeaddr+i);
        s[i] = c;
    }
    s[12] = '\0';
    return s;
}
#endif

static void pairing(void)
{
    enter_command_mode();
    SEND_COMMAND("SR,Z\r\n");   // remove remote address
    SEND_COMMAND("R,1\r\n");    // reboot
    exit_command_mode();
}

bool command_extra(uint8_t code)
{
    uint32_t t;
    uint16_t b;
    static host_driver_t *prev_driver = &rn42_driver;
    switch (code) {
        case KC_H:
        case KC_SLASH: /* ? */
            print("\n\n----- Bluetooth RN-42 Help -----\n");
            print("Del: enter/exit config mode(auto_connect/disconnect)\n");
            print("i:   RN-42 info\n");
            print("b:   battery voltage\n");
            print("i:       RN-42 info\n");
            print("b:       battery voltage\n");
            print("Del:     enter/exit RN-42 config mode\n");
            print("Slck:    RN-42 initialize\n");
#if 0
            print("1-4:     restore link\n");
            print("F1-F4:   store link\n");
#endif
            print("p:       pairing\n");

            if (config_mode) {
                return true;
            } else {
                print("u:   Force USB mode\n");
                print("u:       toggle Force USB mode\n");
                return false;   // to display default command help
            }
        case KC_DELETE:
            if (rn42_autoconnecting()) {
                prev_driver = host_get_driver();
                clear_keyboard();
                _delay_ms(500);
                host_set_driver(&rn42_config_driver);   // null driver; not to send a key to host
                rn42_disconnect();
                print("\nRN-42: disconnect\n");
                print("Enter config mode\n");
                print("type $$$ to start and + for local echo\n");
                command_state = CONSOLE;
                config_mode = true;
            } else {
                rn42_autoconnect();
                print("\nRN-42: auto_connect\n");
                print("Exit config mode\n");
                command_state = ONESHOT;
                config_mode = false;
                //clear_keyboard();
                host_set_driver(prev_driver);
            }
        case KC_P:
            pairing();
            return true;
        case KC_U:
            if (config_mode) return false;
            if (force_usb) {
                print("Auto mode\n");
                force_usb = false;
            } else {
                print("USB mode\n");
                force_usb = true;
                clear_keyboard();
                host_set_driver(&lufa_driver);
            }
#if 0
        /* Store link address to EEPROM */
        case KC_F1:
            store_link(RN42_LINK0);
            return true;
        case KC_F2:
            store_link(RN42_LINK1);
            return true;
        case KC_F3:
            store_link(RN42_LINK2);
            return true;
        case KC_F4:
            store_link(RN42_LINK3);
            return true;
        /* Restore link address to EEPROM */
        case KC_1:
            restore_link(RN42_LINK0);
            return true;
        case KC_2:
            restore_link(RN42_LINK1);
            return true;
        case KC_3:
            restore_link(RN42_LINK2);
            return true;
        case KC_4:
            restore_link(RN42_LINK3);
            return true;
#endif
        case KC_I:
            print("\n----- RN-42 info -----\n");
            xprintf("protocol: %s\n", (host_get_driver() == &rn42_driver) ? "RN-42" : "LUFA");
            xprintf("force_usb: %X\n", force_usb);
            xprintf("rn42: %s\n", rn42_rts() ? "OFF" : (rn42_linked() ? "CONN" : "ON"));
            xprintf("rn42_autoconnecting(): %X\n", rn42_autoconnecting());
            xprintf("rn42_linked(): %X\n", rn42_linked());
            xprintf("rn42_rts(): %X\n", rn42_rts());
            xprintf("config_mode: %X\n", config_mode);
            xprintf("USB State: %s\n",
                    (USB_DeviceState == DEVICE_STATE_Unattached) ? "Unattached" :
                    (USB_DeviceState == DEVICE_STATE_Powered) ? "Powered" :
                    (USB_DeviceState == DEVICE_STATE_Default) ? "Default" :
                    (USB_DeviceState == DEVICE_STATE_Addressed) ? "Addressed" :
                    (USB_DeviceState == DEVICE_STATE_Configured) ? "Configured" :
                    (USB_DeviceState == DEVICE_STATE_Suspended) ? "Suspended" : "?");
            xprintf("battery: ");
            switch (battery_status()) {
                case FULL_CHARGED:  xprintf("FULL"); break;
                case CHARGING:      xprintf("CHARG"); break;
                case DISCHARGING:   xprintf("DISCHG"); break;
                case LOW_VOLTAGE:   xprintf("LOW"); break;
                default:            xprintf("?"); break;
            };
            xprintf("\n");
            xprintf("RemoteWakeupEnabled: %X\n", USB_Device_RemoteWakeupEnabled);
            xprintf("VBUS: %X\n", USBSTA&(1<<VBUS));
            xprintf("battery_charging: %X\n", battery_charging());
            xprintf("battery_status: %X\n", battery_status());
            t = timer_read32()/1000;
            uint8_t d = t/3600/24;
            uint8_t h = t/3600;
            uint8_t m = t%3600/60;
            uint8_t s = t%60;
            xprintf("uptime: %02u %02u:%02u:%02u\n", d, h, m, s);
#if 0
            xprintf("LINK0: %s\r\n", get_link(RN42_LINK0));
            xprintf("LINK1: %s\r\n", get_link(RN42_LINK1));
            xprintf("LINK2: %s\r\n", get_link(RN42_LINK2));
            xprintf("LINK3: %s\r\n", get_link(RN42_LINK3));
#endif
            return true;
        case KC_B:
            // battery monitor


@@ 210,24 365,53 @@ bool command_extra(uint8_t code)
            xprintf("%02u:",   t%3600/60);
            xprintf("%02u\n",  t%60);
            return true;
        case KC_U:
            if (config_mode) return false;
            if (force_usb) {
                print("Auto mode\n");
                force_usb = false;
            } else {
                print("USB mode\n");
                force_usb = true;
                clear_keyboard();
                host_set_driver(&lufa_driver);
            }
            return true;
        case KC_DELETE:
            /* RN-42 Command mode */
            if (rn42_autoconnecting()) {
                enter_command_mode();

                command_state = CONSOLE;
                config_mode = true;
            } else {
                exit_command_mode();

                command_state = ONESHOT;
                config_mode = false;
            }
            return true;
        case KC_SCROLLLOCK:
            init_rn42();
            return true;
        default:
            if (config_mode)
                return true;
            else
                return false;   // exec default command
                return false;   // yield to default command
    }
    return true;
}

/*
 * RN-42 Command mode
 * sends charactors to the module
 */
static uint8_t code2asc(uint8_t code);
bool command_console_extra(uint8_t code)
{
    switch (code) {
        default:
            rn42_putc(code2asc(code));
            return true;
    }
    return false;
    rn42_putc(code2asc(code));
    return true;
}

// convert keycode into ascii charactor

R keyboard/hhkb_rn42/rn42/rn42_task.h => keyboard/hhkb/rn42/rn42_task.h +0 -0
R keyboard/hhkb_rn42/rn42/suart.S => keyboard/hhkb/rn42/suart.S +0 -0
R keyboard/hhkb_rn42/rn42/suart.h => keyboard/hhkb/rn42/suart.h +0 -0
D keyboard/hhkb_rn42/MEMO.txt => keyboard/hhkb_rn42/MEMO.txt +0 -523
@@ 1,523 0,0 @@
Roving RN-42
============

Bug:
- with Nexus5 keyboard and mouse are very laggy.

- lose USB connection during power-down mode
    - USB initialize code in main() causes this - WRONG
    - Do not power-down during USB connection is active - DONE 11/11
        (USB_DeviceState == USB_DEVICE_Configured) is used to check USB connection
        matrix_power_down() matrix.c - 11/23

Todo:

Design:
- remove MCU dependent power saving code from core/keyboard
    - it should be located in project matrix.c - DONE 11/23
- HHKB matrix.c needs matrix_prev?
    - is_modified() is obsolete now. really needs?


LUFA:
USB connection check: state of USB deivce
- USB_DeviceState:
    USB_Deivce_State_t { Unattached, Powered, Default, Addressed, Configured*, Suspended* }
- USB_IsInitialized: state of LUFA core setup
    becomes true in USB_Init()  USBController_AVR8.c
    becomes false in USB_Disable()  USBController_AVR8.c
- USB_VBUS_GetStatus(): state of VBUS(power/connection)
- USB_Disable() detaches, disables all interrupts, controller, PLL, regulater.


Power saving:
- confirm suspend mode lufa.c: matrix_power_*, suspend_wakeup_condition
- 8MHz clock
- When not connected in a few minutes get into deep sleep to save battery life
- CTS is needed for waking up from deep sleep? How deep sleep is activated?
- firmware controlled 3.3V DC converter to switch on/off BT module
- sleep MCU and BT module(keyboard is not used)
- deep sleep MCU and BT module(keyboard is not used for long time)
- deep sleep MCU and turn off BT module(keyboard is not used and not connected)
- Battery ADC; switching, high resistance
    - switching gnd end of divider with PF4
    - high resistor 100K/1M?
        capacitor   10nF
        http://www.eevblog.com/forum/beginners/measuring-battery-voltage-without-consuming-current/
- During USB suspend change clock source to internal RC from external Xtal(6.8)
- FRZCLK: you can freeze clock for power saving. still WAKEUPI and VBUSTI interrupts are available while freezing.(21.7.3)
- Suspend: Clear Suspend Bit, Freeze clock, disable PLL, MCU sleep(21.13)

Improving:
- BT LED; connecting, linked, sleeping, deep sleeping
- Battry LED; blink(using timer?)
- move rn42 to protocol directory when it becomes reusable stack
- LUFA sendchar should be buffered and serial_uart.c buffur size is too large(256).
- ADC resolution
    AVR120
    AVR32138

Testing:
- Factroy reset doesn't work; need to **test again** 10K pull-up is too high?
- Lipo voltage ADC value is not stabilized
- DCDC converter: squeaky inducter; try other inductors

- Keymap layer bug: during space is pressed(mousekey) press Fn(HHKB) then release space before Fn, in result HHKB layer is locked(toggled) unintentionally.


Done:
- low battery alert(solid light) 09/04


Power routing
-------------
Current:
(USB)   +---(Lipo)
 |      |     |
 |      |  +------+     DPDT
 |      |  |Switch/-----------------------+
 |      |  +------+                       |
 | +-------+  |                           |
 +-|Charger|  |                           |
 | +-------+  |     +---+                 |
 |            |     |MCU|                 |
 |            |     +---+                 |
 |            |      |                    |
 |            |      |                    |
+--------------+  +-----+  +------+   +---/--+    +-----+
|Power Selector|--|DC 5V|--|DC3.3V|---|Switch|----|RN-42|
+--------------+  +-----+  +------+   +------+    +-----+
USB Power is boosted unnecessarily, not harmful?

Idea 1:
(USB)   +---(Lipo)
 |      |     |
 |      |  +------+     DPDT
 |      |  |Switch/----------+
 |      |  +------+          |
 | +-------+  |              |
 +-|Charger|  |              |
 | +-------+  |     +---+    |
 |         +-----+  |MCU|    |
 |         |DC 5V|  +---+    |
 |         +-----+   |       |
 |            |      |       |
+--------------+     |   +---/--+    +------+     +-----+
|Power Selector|-----+---|Switch|----|DC3.3V|-----|RN-42|
+--------------+         +------+    +------+     +-----+
To enable BT when USB powered it still needs to turn siwtch on, Lipo consumes quinscent current at 5V converter in vain.(Not good)

Idea 2:
(USB)   +---(Lipo)
 |      |     |
 |      |  +------+
 |      |  |Switch|
 |      |  +------+
 | +-------+  |
 +-|Charger|  |
 | +-------+  |     +---+
 |         +-----+  |MCU|----+ Controlled by firmware
 |         |DC 5V|  +---+    | On: Lipo powered
 |         +-----+   |       | Off: USB powered
 |            |      |       |enable
+--------------+     |   +------+     +-----+
|Power Selector|-----+---|DC3.3V|-----|RN-42|
+--------------+         +------+     +-----+
MCU can controlled power of RN-42 without hardware switch.
When USB powered and switch is on Lipo consumes quinscent current at 5V converter in vain.(Not good)

Idea 3:
(USB)   +---(Lipo)
 |      |     |
 |      |  +------+
 |      |  |Switch|SPST(or without)
 |      |  +------+
 | +-------+  |
 +-|Charger|  |
 | +-------+  |     +---+
 |            |     |MCU|----+ Controlled by firmware
 |            |     +---+    | On: Lipo powered
 |            |      |       | Off: USB powered
 |            |      |       |enable
+--------------+ +-----+ +------+     +-----+
|Power Selector|-|DC 5V|-|DC3.3V|-----|RN-42|
+--------------+ +-----+ +------+     +-----+
Switch is needed to save Lipo when not used because decent power saving is not available now. If firmware can turn off BT module completely and make MCU deep sleep the switch will be not even needed.





DONE:
- BT_INDICATOR LED turns on wrongly when touching line or pin.  -- pull-up enabled on PF6/GPIO2 08/30
- Lipo charger configuration: fast charge time:  USB charger spec? -- used 2kohm
- use LED of charger to alarm low battery. LED should be powered directly from Lipo? - cancel; powered from VUSB
- Use RTS in serial_uart.c to resolve missing chars from help message of RN-42 - done
- CTS/RTS lines are needed? just connect in loop back if no flow control is needed. - done
- add IO pin to charger status CHRG; LED control(low) and detect charge status(input HiZ) 07.24
- LINKED: add trace on PIO2 to PF6   07.24
- Lipo voltage ADC sensing
- Lipo charger MCP73831: needs capacitor 4.7uF *2
- USB connection check - 07.01
- BT on/off check: whether RX line is pulled up? - checking RTS 07.01
- USB/BT switching  BT is on -> BT, BT is off -> USB - 07.01
- Under voltage lock out UVLO for protection of Lipo - Lipo has discharge protection at 3.100V    07.01
- Power saving: HHKB scan, BT radio control - 9h with 850mAh, this is enough   07.01
- Power selector doesn't work; Q4 MOSFET leaks from Lipo to USB power line. -- use Schottky instead 07/04



TROUBLE SHOOT
-------------
07/16   After fix of voltage dividor on GPIO6, had a trouble that it could not send a char to BT module, though could receive.
        Found R8 had wrong 1K resistor and changed to 10K, after that it can send to the module again. Not sure how it had sent with the wrong 1K before.

07/18   On Linux, had an USB related trouble; keyobard or console didn't work for some reason. Changing PID cured this problem. Very annoying, took very long time before resolved it.



Lipo
----
850mA lasts around 9 hours(07/28)

Sparkfun Polymer Lithium Ion Battery 850mAh:
https://www.sparkfun.com/products/341
Lipo Cell spec:
https://www.sparkfun.com/datasheets/Batteries/063048%20Li-polymer.pdf
Protection spec:
http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Prototyping/BatteryProtection.pdf
                                min     typical max
    over-charge                 4.255   4.280   4.305
    over-charge discover?       4.030   4.080   4.130        
    over-discharge              2.827   2.900   2.973
    over-discharge discover     3.022   3.100   3.178

ADC voltage monitor:    voltage divider 10K+10K(0.5)
                        ADC=V*0.5/2.56*1024

    V       ADC
    ------------------
    4.20    0x347(839)
    3.10    0x26b(619)
    



Configuration
-------------
Ver 6.15 04/26/2013
(c) Roving Networks
***Settings***
BTA=0006664B3AE3
BTName=tmkBT-3AE3
Baudrt(SW4)=115K
Mode  =DTR
Authen=2
Bonded=0
Rem=000000000000
***ADVANCED Settings***
SrvName= keyboard/mouse
SrvClass=0000
DevClass=0000
InqWindw=0100
PagWindw=0100
CfgTimer=255
StatuStr=NULL
HidFlags=3c
DTRtimer=8
KeySwapr=0
***OTHER Settings***
Profile= HID
CfgChar= $
SniffEna=8010
LowPower=0
TX Power=0
IOPorts= 0
IOValues=0
Sleeptmr=0
DebugMod=0
RoleSwch=0



Serial connection
-----------------
Serial line:    115200bps, 8bit, 1-stopbit, non-parity, no flow control
SSP:            115200bps, 8bit, 1-stopbit, non-parity, no flow control(via Bluetooth)

To enter command mode disconnect the module from host and type '$$$'.(you will see 'CMD')
To exit type '---'(you will see 'END') and '+' to get local echo.



Setting command mode
--------------------
S-,tmkBT            // Device name
SS,keyboard/mouse   // service name
SM,4                // Auto Connect DTR mode
SW,8010             // Sniff enable 0x10*0.625ms=10ms; 50ms is laggish and not much power save
S~,6                // HID profile
SH,003C             // HID register
SY,0004             // Transmit power




Other options:
SC,0000         // COD: 000005C0    (see HID spec/Bluegiga doc)
SD,05C0         //     bit 12-8         7           6           5-0
                //         00101        1           1           0
                //         peripheral   pointing    keybaord    joystick, gamepad, ...
SM,6                // Pairing mode: auto connect
SM,4                // Master mode: Connection can be controled with GPIO6




HID profile
-----------
S~,6    HID profile
S~,0    SPP profile
R,1     reboot


Apple iOS
---------
Keyboard can be used with iPhone, but mouse cannot.
To operate iOS with keyboard is not so useful, though.
There may be iOS specific scancodes?


HID flag register
-----------------
SH,0200
GH

10 0000 0000(0200)  default
00 0011 1000(0038)  Combo
|| |  | |\_\____ number of paired devices to which the module can reconnect
|| |  | \_______ send out reports over UART (0xFF <len> <data>)
|| \__\_________ descriptor type
|\______________ toggle virtual keyboard on iOS when first connected
\_______________ Force HID mode if GPIO11 is high on power-up

    Descriptor type:
    0000:   keybaord
    0001:   Game Pad
    0010:   Mouse
    0011:   Combo
    0100:   Joystick
    1xxx:   reserved


Out report - Indicator
----------------------
0xFE 0x02 0x01 <LED_state>


LED Status
----------
Configuring                     10 times per sec
Startup/configuration timer     2 times per sec
Discoverable/Inquiring/Idle     once per sec
Connected                       solid on


Pairing
-------
First, host initiates pairing process and once it is done, auto connect will work thereafter.
SM,3        Master mode
SM,4        Auto Connect DTR Mode uses GPIO6 to make and break connection(Mode =DTR)
                confirm: auto connect works and control connection with GPIO6
SM,5        Auto Connect ANY Mode (Mode =ANY)
                each time GPIO is set, make inquiry and connect to the first found device
SM,6        automatically reconnect(Mode =Pair)
                confirm: auto connect works well but difficult to enter command mode.

SR,Z        removes all remote addresses for reconnecting.
                can be used to connect another host
SR,I        registers last inquiry address


Fast data mode
--------------
The module enters fast data mode after 'remote configuration timer' window is passed from power on.
In this mode the module does not accept '$$$' to enter command mode.

Power Management
----------------
Inquiry and Page window     Idle or Active  (3.1.1)
    Downside: delay in discovery or connection time
    SI,         // set inquiry scan window(discovery) on/off duty?
    SJ,         // set page scan window(connection)
    This reduces averaege power >20mA to 5mA(3mA in Sniff mode)

Sniff mode                  Transmit
    Sniff mode is disabled by default and radio is active continuously when connected.(25-30mA)
    In Sniff mode the radio wakes up intermittently and sleeps in very low power mode.(2mA)
    SW,<val>    // set interval timer(*0.625ms) 0000-7FFF

Deep sleep                  Idle            (3.1.2)
    In this mode the module shuts down completly and only draws about 300uA. To enable this set the most signifant bit(0x8000) of Sniff interaval timer.
    SW,8320     // deep sleep enable(interval=0x320*0.625=500ms)
    In normal sleep the firmware is still running in idle mode, and wakes up about 20 times per second to check ports, update LEDs, etc. During deep sleep, the firmware actually stops runnig some tasks and the LEDs only update about once per second.
    To wake from deep sleep there are three ways: (in worst case wake up takes 5ms)
        *send a charactor to the UART(first charactor will be lost)
        *toggle CTS low to high and wait 5ms
        *wake automatically every slot time(<val>*0.625ms)
    Once the radio is awake it stay active for exactly 1 second of inactivity and then sleeps again.
    Downside: latency and data loss

Disable Output driver       Idle or Active  (3.1.3)
    S%,1000     // set all GPIO pins(0-11) to inputs.

Lower Transmit Power        Idle or Active  (3.1.4)
    SY,<hex>    // transmit power setting(takes effect after a power cycle and reboot)
    Downside: reducing effective range


Optimizig for Latency
---------------------
By default the firmware is optimized for throughput.
SQ,16           // set latency bit
SQ,0            // unset latency bit


Configuration timer settings
----------------------------
Remote configuration is used for the module to be configured with various commands over Bluetooth(SPP profile only?).

The module has remote configuration timer to allow remote configuration over Bluetooth after power up in Slave mode. In Master modes the remote configuration timer is set to 0(no remote configuration). (In Trigger Master mode the timer is used as an idle timer to break the connection after time expires with no charactors receive.)
    ST,0        // no remote, no local when connected
    ST,<1-252>  // local and remote with timeout in seconds from power up
    ST,253      // local only       without timeout
    ST,254      // remote only      without timeout
    ST,255      // local and remote without timeout


Android
-------
3.7.1.5 Note: To connect with Android phone the modules must wake up 11ms every 2.5seconds.


Commands
--------
SC,
SM,<val>
SD,         
SP,<string>             Pin code(alpahnumeric)
SQ,<mask>               Special configuration(GPIO, discovery mode, low latency, reboot, UART)
SR,<hex>                Store remote address
SR,Z                    Erase all address
SS,<string>             Set service name(1-20)**
ST,<val>                Remote configuration timer(Master:0, Slave:0-255, Triger:as idle timer)
SU,<val>                UART baud rate
SW,<val>                low-power sniff mode** deep sleep and wake up every 625us * <val>
SX,<0|1>                bonding enable  only acceps device that matches the stored address
SY,<hex>                power setting** 
SZ,<val>                non-standard raw baud rate  <val>=baud*0.004096
S~,<val>                Profile     0:SPP, 5:APL, 6:HID
S-,<string>             Device name     -15 alphanumeric charactors
S?,<0|1>                role switch enable
S$,<char>               command mode char
$|,<hex>                low-power connect mode  deep sleep/active(discoverable and connectable) cycle
D                       display basic setting
E                       display extended setting
GB                      display the device's Bluetooth address
GF                      display Bluetooth address of connected device
GK                      show connection status
GR                      show remote address for reconnecting
G&                      show GPIO pin
G<char>                 show stored setting
+                       toggle local echo on/off
&                       show GPIO 3,4,6,7(DIP switch)
C                       connect to stored remote address
C,<address>             connect last address
CFI                     connect and go into fast data mode
CFR                     connect and go into fast data mode
CT,<address>,<val>      connect to the address and disconnect after val?
F,1                     fast data mod:
H                       display help
I,<time>,<cod>          inquiry scan with <cod>
IN
IQ                      scan
IS                      inquiry scan with 001F00
J                       hide pin code
K,                      kill    disconnects current connection
L                       link quality
M                       show modem signlal status
O                       display other settings
P,<car>                 pass through?
Q                       quiet mode  make the module not discoverable
Q,0                     discoverable and connectable
Q,1                     not discoverable and not connectable
Q,2                     not discoverable and connectable
Q,?                     display current quiet mode
R,1                     reboot
T,<0|1>                 pass received data while in command mode
U,<baud>,<parity>       change UART setting tentatively
V                       display firmware version
W                       wake from quiet mode    enable discovery and connection
Z                       deep sleep mode(<2mA)



help
----
*** SET COMMANDS ***
SA,<3,0>   - Authentication
SC,<hex>   - Service Class
SD,<hex>   - Device Class
SE,<1-16>  - UUID
SF,1       - Factory Defaults
SH,<hex>   - HID flags
SI,<hex>   - Inquiry Scan Window
SJ,<hex>   - Page Scan Window
SL,<E,O,N> - Parity
SM,<0-5>   - Mode (0=slav,1=mstr,2=trig,3=auto,4=DTR,5=Any)
SN,<name>  - Name
SO,<text>  - conn/discon Status
SP,<text>  - Pin Code
SR,<adr>   - Remote Address
SS,<text>  - Service Name
ST,<num>   - Config Timer
SU,<rate>  - Baudrate
SW,<hex>   - Sniff Rate
SX,<1,0>   - Bonding
SY,<hex>   - TX power
SZ,<num>   - Raw Baudrate
S~,<0-6>   - Profile (0=SPP,1=DCE,2=DTE,3=MDM,4=D&S,6=HID
S?,<0-1>   - role switch
S$,<char>  - CMD mode char
S@,<hex>   - io port dir
S&,<hex>   - io port val
S%,<hex>   - io boot dir
S^,<hex>   - io boot val
S*,<hex>   - pio(8-11) set
S|,<hex>   - low power timers
S+,<num>   - DTR timer
S=,<hex>   - Key mapper
S:,<num>   - sleep timer
*** DISPLAY      ***
D     - Basic Settings
E     - Extended Settings
G<X>  - Stored setting
GB    - BT Address
GF    - BT Address of Last Connection
GK    - Connect Status
G&    - I/O Ports
V     - Firmare version
*** OTHER        ***
C,<adr>    - Connect
F,1        - Fast Mode
I,<time>,<cod> - Device Scan Inquiry
J          - Hide Pin Code
K,         - Kill (disconnect)
L,         - toggle local echo
P,<text>   - Pass Thru
Q          - Quiet (no discovery)
R,1        - Reboot
T,<0,1>    - send data in CMD mode
U,<rate>,<E,O,N> - Temp Uart Change
Z          - low power sleep
&          - Read switches

D keyboard/hhkb_rn42/hhkb_avr.h => keyboard/hhkb_rn42/hhkb_avr.h +0 -164
@@ 1,164 0,0 @@
#ifndef HHKB_AVR_H
#define HHKB_AVR_H

#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>


// Timer resolution check
#if (1000000/TIMER_RAW_FREQ > 20)
#   error "Timer resolution(>20us) is not enough for HHKB matrix scan tweak on V-USB."
#endif


/*
 * HHKB Matrix I/O
 *
 * row:     HC4051[A,B,C]  selects scan row0-7
 * row-ext: [En0,En1] row extention for JP
 * col:     LS145[A,B,C,D] selects scan col0-7 and enable(D)
 * key:     on: 0/off: 1
 * prev:    hysteresis control: assert(1) when previous key state is on
 */


#if defined(__AVR_ATmega32U4__)
/*
 * For TMK HHKB alt controller(ATMega32U4)
 *
 * row:     PB0-2
 * col:     PB3-5,6
 * key:     PD7(pull-uped)
 * prev:    PB7
 * power:   PD4(L:off/H:on)
 * row-ext: PC6,7 for HHKB JP(active low)
 */
static inline void KEY_ENABLE(void) { (PORTB &= ~(1<<6)); }
static inline void KEY_UNABLE(void) { (PORTB |=  (1<<6)); }
static inline bool KEY_STATE(void) { return (PIND & (1<<7)); }
static inline void KEY_PREV_ON(void) { (PORTB |=  (1<<7)); }
static inline void KEY_PREV_OFF(void) { (PORTB &= ~(1<<7)); }
#ifdef HHKB_POWER_SAVING
static inline void KEY_POWER_ON(void) {
    DDRB = 0xFF; PORTB = 0x40;          // change pins output
    DDRD |= (1<<4); PORTD |= (1<<4);    // MOS FET switch on
    /* Without this wait you will miss or get false key events. */
    _delay_ms(5);                       // wait for powering up
}
static inline void KEY_POWER_OFF(void) {
    /* input with pull-up consumes less than without it when pin is open. */
    DDRB = 0x00; PORTB = 0xFF;          // change pins input with pull-up
    DDRD |= (1<<4); PORTD &= ~(1<<4);   // MOS FET switch off
}
#else
static inline void KEY_POWER_ON(void) {}
static inline void KEY_POWER_OFF(void) {}
#endif
static inline void KEY_INIT(void)
{
    /* row,col,prev: output */
    DDRB  = 0xFF;
    PORTB = 0x40;   // unable
    /* key: input with pull-up */
    DDRD  &= ~0x80;
    PORTD |=  0x80;
#ifdef HHKB_JP
    /* row extention for HHKB JP */
    DDRC  |= (1<<6|1<<7);
    PORTC |= (1<<6|1<<7);
#endif
    KEY_UNABLE();
    KEY_PREV_OFF();

    KEY_POWER_ON();
}
static inline void KEY_SELECT(uint8_t ROW, uint8_t COL)
{
    PORTB = (PORTB & 0xC0) | (((COL) & 0x07)<<3) | ((ROW) & 0x07);
#ifdef HHKB_JP
    if ((ROW) & 0x08) PORTC = (PORTC & ~(1<<6|1<<7)) | (1<<6);
    else              PORTC = (PORTC & ~(1<<6|1<<7)) | (1<<7);
#endif
}


#elif defined(__AVR_AT90USB1286__)
/*
 * For Teensy++(AT90USB1286)
 *
 *                          HHKB pro    HHKB pro2
 * row:     PB0-2           (6-8)       (5-7)
 * col:     PB3-5,6         (9-12)      (8-11)
 * key:     PE6(pull-uped)  (4)         (3)
 * prev:    PE7             (5)         (4)
 *
 * TODO: convert into 'staitc inline' function
 */
#define KEY_INIT()              do {    \
    DDRB |= 0x7F;                       \
    DDRE |=  (1<<7);                    \
    DDRE &= ~(1<<6);                    \
    PORTE |= (1<<6);                    \
} while (0)
#define KEY_SELECT(ROW, COL)    (PORTB = (PORTB & 0xC0) |       \
                                         (((COL) & 0x07)<<3) |  \
                                         ((ROW) & 0x07))
#define KEY_ENABLE()            (PORTB &= ~(1<<6))
#define KEY_UNABLE()            (PORTB |=  (1<<6))
#define KEY_STATE()             (PINE & (1<<6))
#define KEY_PREV_ON()           (PORTE |=  (1<<7))
#define KEY_PREV_OFF()          (PORTE &= ~(1<<7))
#define KEY_POWER_ON()
#define KEY_POWER_OFF()


#else
#   error "define code for matrix scan"
#endif


#if 0
// For ATMega328P with V-USB
//
// #elif defined(__AVR_ATmega328P__)
// Ports for V-USB
// key:     PB0(pull-uped)
// prev:    PB1
// row:     PB2-4
// col:     PC0-2,3
// power:   PB5(Low:on/Hi-z:off)
#define KEY_INIT()              do {    \
    DDRB  |= 0x3E;                      \
    DDRB  &= ~(1<<0);                   \
    PORTB |= 1<<0;                      \
    DDRC  |= 0x0F;                      \
    KEY_UNABLE();                       \
    KEY_PREV_OFF();                     \
} while (0)
#define KEY_SELECT(ROW, COL)    do {    \
    PORTB = (PORTB & 0xE3) | ((ROW) & 0x07)<<2; \
    PORTC = (PORTC & 0xF8) | ((COL) & 0x07);    \
} while (0)
#define KEY_ENABLE()            (PORTC &= ~(1<<3))
#define KEY_UNABLE()            (PORTC |=  (1<<3))
#define KEY_STATE()             (PINB & (1<<0))
#define KEY_PREV_ON()           (PORTB |=  (1<<1))
#define KEY_PREV_OFF()          (PORTB &= ~(1<<1))
// Power supply switching
#define KEY_POWER_ON()          do {    \
    KEY_INIT();                         \
    PORTB &= ~(1<<5);                   \
    _delay_ms(1);                       \
} while (0)
#define KEY_POWER_OFF()         do {    \
    DDRB  &= ~0x3F;                     \
    PORTB &= ~0x3F;                     \
    DDRC  &= ~0x0F;                     \
    PORTC &= ~0x0F;                     \
} while (0)
#endif

#endif

D keyboard/hhkb_rn42/keymap_common.h => keyboard/hhkb_rn42/keymap_common.h +0 -84
@@ 1,84 0,0 @@
/*
Copyright 2012,2013 Jun Wako <wakojun@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEYMAP_COMMON_H
#define KEYMAP_COMMON_H

#include <stdint.h>
#include <stdbool.h>
#include "keycode.h"
#include "action.h"
#include "action_code.h"
#include "action_layer.h"
#include "action_macro.h"
#include "action_util.h"
#include "report.h"
#include "host.h"
#include "print.h"
#include "debug.h"
#include "keymap.h"


extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
extern const uint16_t fn_actions[];


#define KEYMAP( \
    K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \
    K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \
    K33, K04, K03, K14, K15, K24, K25, K45, K44, K65, K64, K74, K53, \
    K34, K05, K06, K07, K16, K17, K26, K46, K66, K76, K75, K55, K54, \
         K35, K36,           K37,                K57, K56 \
) \
{ \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
    { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO    }, \
    { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \
    { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_NO    }, \
    { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \
    { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_NO    }, \
    { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO    } \
}


#define KEYMAP_JP( \
    K02, K32, K62, K22, K12, K52, K72, KA2, K92, K82, KB2, KE2, KF2, KD2, KC2, \
    K03, K63, K23, K13, K53, K73, KA3, K93, K83, KB3, KE3, KF3, KD3, \
    K06, K66, K26, K16, K56, K76, KA6, K96, K86, KB6, KE6, KF6, KD6, KC6, \
    K05, K65, K25, K15, K55, K75, KA5, K95, K85, KB5, KE5, KF5, KD5, KC5, \
    K04, K34, K64, K24, K14,      K74,      K94, K84, KB4, KE4, KF4, KD4, KC4 \
) \
{ \
    { KC_NO,    KC_NO,    KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##K32, KC_NO,    KC_##K34, KC_NO,    KC_NO,    KC_NO    }, \
    { KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##K52, KC_##K53, KC_NO,    KC_##K55, KC_##K56, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##K92, KC_##K93, KC_##K94, KC_##K95, KC_##K96, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##KA2, KC_##KA3, KC_NO,    KC_##KA5, KC_##KA6, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##KB2, KC_##KB3, KC_##KB4, KC_##KB5, KC_##KB6, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##KC2, KC_NO,    KC_##KC4, KC_##KC5, KC_##KC6, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##KD2, KC_##KD3, KC_##KD4, KC_##KD5, KC_##KD6, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##KE2, KC_##KE3, KC_##KE4, KC_##KE5, KC_##KE6, KC_NO    }, \
    { KC_NO,    KC_NO,    KC_##KF2, KC_##KF3, KC_##KF4, KC_##KF5, KC_##KF6, KC_NO    }  \
}

#endif

D keyboard/hhkb_rn42/keymap_hasu.c => keyboard/hhkb_rn42/keymap_hasu.c +0 -282
@@ 1,282 0,0 @@
/* 
 * Hasu: my personal keymap
 */
#include "keymap_common.h"


#ifdef KEYMAP_SECTION_ENABLE
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = {
#else
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
#endif
    /* Layer 0: Default Layer
     * ,-----------------------------------------------------------.
     * |Esc|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|  \|  `|
     * |-----------------------------------------------------------|
     * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|Backs|
     * |-----------------------------------------------------------|
     * |Contro|  A|  S|  D|  F|  G|  H|  J|  K|  L|Fn3|  '|Fn6     |
     * |-----------------------------------------------------------|
     * |Fn7     |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|Fn2|Shift |Fn1|
     * `-----------------------------------------------------------'
     *       |Gui|Alt  |         Fn4           |Fn5  |Gui|
     *       `-------------------------------------------'
     */
    [0] = \
    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,FN6, \
           FN7, Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, FN2, RSFT,FN1, \
                LGUI,LALT,          FN4,                FN5, RGUI),

    /* Layer 1: HHKB mode[HHKB Fn]
     * ,-----------------------------------------------------------.
     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |Caps |   |   |   |   |   |   |   |Psc|Slk|Pus|Up |   |Backs|
     * |-----------------------------------------------------------|
     * |Contro|VoD|VoU|Mut|   |   |  *|  /|Hom|PgU|Lef|Rig|Enter   |
     * |-----------------------------------------------------------|
     * |Shift   |   |   |   |   |   |  +|  -|End|PgD|Dow|Shift |   |
     * `-----------------------------------------------------------'
     *       |Gui|Alt  |         Space         |Alt  |Gui|
     *       `-------------------------------------------'
     */ 
    [1] = \
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           CAPS,NO,  NO,  NO,  NO,  NO,  NO,  NO,  PSCR,SLCK,PAUS, UP,  NO,  BSPC, \
           LCTL,VOLD,VOLU,MUTE,NO,  NO,  PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
           LSFT,NO,  NO,  NO,  NO,  NO,  PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
                LGUI,LALT,          SPC,                RALT,RGUI),

    /* Layer 2: Vi mode[Slash]
     * ,-----------------------------------------------------------.
     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |Tab  |Hom|PgD|Up |PgU|End|Hom|PgD|PgUlEnd|   |   |   |Backs|
     * |-----------------------------------------------------------|
     * |Contro|   |Lef|Dow|Rig|   |Lef|Dow|Up |Rig|   |   |Return  |
     * |-----------------------------------------------------------|
     * |Shift   |   |   |   |   |   |Hom|PgD|PgUlEnd|Fn0|Shift |   |
     * `-----------------------------------------------------------'
     *       |Gui|Alt  |          Space        |Alt  |Gui|
     *       `-------------------------------------------'
     */
    [2] = \
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           TAB, HOME,PGDN,UP,  PGUP,END, HOME,PGDN,PGUP,END, NO,  NO,  NO,  BSPC, \
           LCTL,NO,  LEFT,DOWN,RGHT,NO,  LEFT,DOWN,UP,  RGHT,NO,  NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  NO,  HOME,PGDN,PGUP,END, TRNS,RSFT,NO, \
                LGUI,LALT,          SPC,                RALT,RGUI),

    /* Layer 3: Mouse mode(IJKL)[Semicolon]
     * ,-----------------------------------------------------------.
     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |Tab  |   |   |   |   |   |MwL|MwD|McU|MwU|MwR|Wbk|Wfr|Alt-T|
     * |-----------------------------------------------------------|
     * |Contro|   |   |   |   |   |Mb2|McL|McD|McR|Fn |   |Return  |
     * |-----------------------------------------------------------|
     * |Shift   |   |   |   |   |Mb3|Mb2|Mb1|Mb4|Mb5|   |Shift |   |
     * `-----------------------------------------------------------'
     *      |Gui |Alt  |          Mb1          |Fn   |Fn |
     *      `--------------------------------------------'
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel8
     */
    [3] = \
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           FN8, NO,  NO,  NO,  NO,  NO,  LEFT,WH_D,MS_U,WH_U,RGHT,FN9, FN10,FN8, \
           LCTL,ACL0,ACL1,ACL2,ACL2,NO,  NO,  MS_L,MS_D,MS_R,TRNS,NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,FN9, FN10,NO,  RSFT,NO, \
                LGUI,LALT,          BTN1,               TRNS,TRNS),

    /* Layer 5: Mouse mode(IJKL)[Space]
     * ,-----------------------------------------------------------.
     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |Tab  |   |   |   |   |   |MwL|MwD|McU|MwU|MwR|Wbk|Wfr|Alt-T|
     * |-----------------------------------------------------------|
     * |Contro|   |   |   |   |   |Mb2|McL|McD|McR|Mb1|   |Return  |
     * |-----------------------------------------------------------|
     * |Shift   |   |   |   |   |Mb3|Mb2|Mb1|Mb4|Mb5|   |Shift |   |
     * `-----------------------------------------------------------'
     *      |Gui |Alt  |          Mb1          |Fn   |Fn |
     *      `--------------------------------------------'
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel8
     */
    [4] = \
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           FN8, NO,  NO,  NO,  NO,  NO,  LEFT,WH_D,MS_U,WH_U,RGHT,FN9, FN10,FN8, \
           LCTL,VOLD,VOLU,MUTE,NO,  NO,  NO,  MS_L,MS_D,MS_R,BTN1,NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,FN9, FN10,NO,  RSFT,NO, \
                LGUI,LALT,          TRNS,               TRNS,TRNS),

#if 0
    /* Layer 3: Mouse mode(HJKL)[Semicolon]
     * ,-----------------------------------------------------------.
     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |Tab  |   |   |   |   |   |MwL|MwD|MwU|MwR|   |   |   |Backs|
     * |-----------------------------------------------------------|
     * |Contro|   |   |   |   |   |McL|McD|McU|McR|Fn0|   |Return  |
     * |-----------------------------------------------------------|
     * |Shift   |   |   |   |   |Mb3|Mb2|Mb1|Mb4|Mb5|   |Shift |   |
     * `-----------------------------------------------------------'
     *      |Gui |Alt  |          Mb1          |Alt  |Fn0|
     *      `--------------------------------------------'
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel 
     */
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           TAB, NO,  NO,  NO,  NO,  NO,  LEFT,WH_D,WH_U,RGHT,NO,  NO,  NO,  BSPC, \
           LCTL,NO,  ACL0,ACL1,ACL2,NO,  MS_L,MS_D,MS_U,MS_R,TRNS,QUOT,ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,FN9, FN10,SLSH,RSFT,NO, \
                LGUI,LALT,          BTN1,               RALT,TRNS),

    /* Layer4: Mouse mode(HJKL)[Space]
     * ,-----------------------------------------------------------.
     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |Tab  |   |   |   |   |   |MwL|MwD|MwU|MwR|   |Wbk|Wfr|Alt-T|
     * |-----------------------------------------------------------|
     * |Contro|   |   |   |   |   |McL|McD|McU|McR|Fn0|   |Return  |
     * |-----------------------------------------------------------|
     * |Shift   |   |   |   |   |Mb3|Mb2|Mb1|Mb4|Mb5|   |Shift |   |
     * `-----------------------------------------------------------'
     *      |Gui |Alt  |          Fn0          |Alt  |Fn0|
     *      `--------------------------------------------'
     * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel 
     */
    KEYMAP(GRV, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
           FN8, NO,  NO,  NO,  NO,  NO,  LEFT,WH_D,WH_U,RGHT,NO,  FN9, FN10,FN8, \
           LCTL,NO,  ACL0,ACL1,ACL2,NO,  MS_L,MS_D,MS_U,MS_R,BTN1,NO,  ENT, \
           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,FN9, FN10,NO,  RSFT,NO, \
                LGUI,LALT,          TRNS,               RALT,RGUI),
#endif
#if 0
    /* Layer x: Matias half-qwerty keyboard style[Space]
     * ,-----------------------------------------------------------.
     * |  -|  0|  9|  8|  7|  6|  5|  4|  3|  2|  1|   |   |   |Esc|
     * |-----------------------------------------------------------|
     * |Backs|  P|  O|  I|  U|  Y|  T|  R|  E|  W|  Q|   |   |Tab  |
     * |-----------------------------------------------------------|
     * |Contro|  ;|  L|  K|  J|  H|  G|  F|  D|  S|  A|Con|Control |
     * |-----------------------------------------------------------|
     * |Shift   |  /|  .|  ,|  M|  N|  B|  V|  C|  X|  Z|Shift |   |
     * `-----------------------------------------------------------'
     *      |Gui |Alt  |          Fn0          |Alt  |Gui|
     *      `--------------------------------------------'
     */
    KEYMAP(MINS,0,   9,   8,   7,   6,   5,   4,   3,   2,   1,   NO,  NO,  NO,  ESC, \
           BSPC,P,   O,   I,   U,   Y,   T,   R,   E,   W,   Q,   NO,  NO,  TAB, \
           LCTL,SCLN,L,   K,   J,   H,   G,   F,   D,   S,   A,   RCTL,RCTL, \
           LSFT,SLSH,DOT, COMM,M,   N,   B,   V,   C,   X,   Z,   RSFT,NO, \
                LGUI,LALT,          TRNS,               RALT,RGUI),
#endif
};



/* id for user defined functions */
enum function_id {
    LSHIFT_LPAREN,
};

enum macro_id {
    HELLO,
    VOLUP,
    ALT_TAB,
};


/*
 * Fn action definition
 */
#ifdef KEYMAP_SECTION_ENABLE
const uint16_t fn_actions[] __attribute__ ((section (".keymap.fn_actions"))) = {
#else
const uint16_t fn_actions[] PROGMEM = {
#endif
    [0] = ACTION_DEFAULT_LAYER_SET(0),                // Default layer(not used)
    [1] = ACTION_LAYER_TAP_TOGGLE(1),                 // HHKB layer(toggle with 5 taps)
    [2] = ACTION_LAYER_TAP_KEY(2, KC_SLASH),          // Cursor layer with Slash*
    [3] = ACTION_LAYER_TAP_KEY(3, KC_SCLN),           // Mousekey layer with Semicolon*
    [4] = ACTION_LAYER_TAP_KEY(4, KC_SPC),            // Mousekey layer with Space
    [5] = ACTION_LAYER_MOMENTARY(4),                  // Mousekey layer(IJKL)
    [6] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_ENT),      // RControl with tap Enter
    [7] = ACTION_MODS_ONESHOT(MOD_LSFT),              // Oneshot Shift
    [8] = ACTION_MACRO(ALT_TAB),                      // Application switching
    [9] = ACTION_MODS_KEY(MOD_LALT, KC_LEFT),
   [10] = ACTION_MODS_KEY(MOD_LALT, KC_RIGHT),

//  [x] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC),        // LControl with tap Backspace
//  [x] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC),         // LControl with tap Esc
//  [x] = ACTION_FUNCTION_TAP(LSHIFT_LPAREN),           // Function: LShift with tap '('
//  [x] = ACTION_MACRO(HELLO),                          // Macro: say hello
//  [x] = ACTION_MACRO(VOLUP),                          // Macro: media key
};


/*
 * Macro definition
 */
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
    switch (id) {
        case HELLO:
            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 (record->event.pressed ?
                    MACRO( D(VOLU), U(VOLU), END ) :
                    MACRO_NONE );
        case ALT_TAB:
            return (record->event.pressed ?
                    MACRO( D(LALT), D(TAB), END ) :
                    MACRO( U(TAB), END ));
    }
    return MACRO_NONE;
}



/*
 * user defined action function
 */
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
    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:
            // 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 {
                    register_mods(MOD_BIT(KC_LSHIFT));
                }
            } else {
                if (record->tap.count > 0 && !(record->tap.interrupted)) {
                    add_weak_mods(MOD_BIT(KC_LSHIFT));
                    send_keyboard_report();
                    register_code(KC_9);
                    unregister_code(KC_9);
                    del_weak_mods(MOD_BIT(KC_LSHIFT));
                    send_keyboard_report();
                    record->tap.count = 0;  // ad hoc: cancel tap
                } else {
                    unregister_mods(MOD_BIT(KC_LSHIFT));
                }
            }
            break;
    }
}

D keyboard/hhkb_rn42/keymap_jp.c => keyboard/hhkb_rn42/keymap_jp.c +0 -50
@@ 1,50 0,0 @@
/* 
 * HHKB JP Layout
 */
#include "keymap_common.h"


#ifdef KEYMAP_SECTION_ENABLE
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = {
#else
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
#endif
    /* Layer 0: Default Layer */
    KEYMAP_JP(ESC, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, JYEN,BSPC, \
              TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC, \
              LCTL,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,BSLS,ENT, \
              LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,RO,  UP,  RSFT, \
              FN0, ZKHK,LGUI,LALT,MHEN,     SPC,      HENK,KANA,RALT,FN0, LEFT,DOWN,RGHT),

    /* Layer 1: HHKB mode (HHKB Fn)
     * ,-----------------------------------------------------------.
     * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |Caps |   |   |   |   |   |   |   |Psc|Slk|Pus|Up |   |     |
     * |------------------------------------------------------`    |
     * |      |VoD|VoU|Mut|   |   |  *|  /|Hom|PgU|Lef|Rig|   |    |
     * |-----------------------------------------------------------|
     * |       |   |   |   |   |   |  +|  -|End|PgD|Dow|   |   |   |
     * |-----------------------------------------------------------|
     * |   ||   |   |   |   |         |   |   |   |   ||   |   |   |
     * `-----------------------------------------------------------'
     */ 
    KEYMAP_JP(PWR, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
              CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS, \
              TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,TRNS,PENT, \
              TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,TRNS,TRNS,TRNS, \
              TRNS,TRNS,TRNS,TRNS,TRNS,     TRNS,     TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS),
};



/*
 * Fn action definition
 */
#ifdef KEYMAP_SECTION_ENABLE
const uint16_t fn_actions[] __attribute__ ((section (".keymap.fn_actions"))) = {
#else
const uint16_t fn_actions[] PROGMEM = {
#endif
    [0] = ACTION_LAYER_MOMENTARY(1),
};

D keyboard/hhkb_rn42/led.c => keyboard/hhkb_rn42/led.c +0 -33
@@ 1,33 0,0 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <avr/io.h>
#include "stdint.h"
#include "led.h"


/* HHKB has no LEDs */
void led_set(uint8_t usb_led)
{
    if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
        DDRD |= (1<<6);
        PORTD |= (1<<6);
    } else {
        DDRD |= (1<<6);
        PORTD &= ~(1<<6);
    }
}

D keyboard/hhkb_rn42/matrix.c => keyboard/hhkb_rn42/matrix.c +0 -191
@@ 1,191 0,0 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
 * scan matrix
 */
#include <stdint.h>
#include <stdbool.h>
#include <util/delay.h>
#include "print.h"
#include "debug.h"
#include "util.h"
#include "timer.h"
#include "matrix.h"
#include "hhkb_avr.h"
#include <avr/wdt.h>
#include "suspend.h"
#include "lufa.h"


// matrix power saving
#define MATRIX_POWER_SAVE       10000
static uint32_t matrix_last_modified = 0;
static bool matrix_power = true;

// matrix state buffer(1:on, 0:off)
static matrix_row_t *matrix;
static matrix_row_t *matrix_prev;
static matrix_row_t _matrix0[MATRIX_ROWS];
static matrix_row_t _matrix1[MATRIX_ROWS];


inline
uint8_t matrix_rows(void)
{
    return MATRIX_ROWS;
}

inline
uint8_t matrix_cols(void)
{
    return MATRIX_COLS;
}

void matrix_init(void)
{
#ifdef DEBUG
    debug_enable = true;
    debug_keyboard = true;
#endif

    KEY_INIT();

    // initialize matrix state: all keys off
    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
    matrix = _matrix0;
    matrix_prev = _matrix1;
}

uint8_t matrix_scan(void)
{
    uint8_t *tmp;

    tmp = matrix_prev;
    matrix_prev = matrix;
    matrix = tmp;

    matrix_power_up();
    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
        for (uint8_t col = 0; col < MATRIX_COLS; col++) {
            KEY_SELECT(row, col);
            _delay_us(5);

            // Not sure this is needed. This just emulates HHKB controller's behaviour.
            if (matrix_prev[row] & (1<<col)) {
                KEY_PREV_ON();
            }
            _delay_us(10);

            // NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE.
            // If V-USB interrupts in this section we could lose 40us or so
            // and would read invalid value from KEY_STATE.
            uint8_t last = TIMER_RAW;

            KEY_ENABLE();

            // Wait for KEY_STATE outputs its value.
            // 1us was ok on one HHKB, but not worked on another.
            // no   wait doesn't work on Teensy++ with pro(1us works)
            // no   wait does    work on tmk PCB(8MHz) with pro2
            // 1us  wait does    work on both of above
            // 1us  wait doesn't work on tmk(16MHz)
            // 5us  wait does    work on tmk(16MHz)
            // 5us  wait does    work on tmk(16MHz/2)
            // 5us  wait does    work on tmk(8MHz)
            // 10us wait does    work on Teensy++ with pro
            // 10us wait does    work on 328p+iwrap with pro
            // 10us wait doesn't work on tmk PCB(8MHz) with pro2(very lagged scan)
            _delay_us(5);

            if (KEY_STATE()) {
                matrix[row] &= ~(1<<col);
            } else {
                matrix[row] |= (1<<col);
            }

            // Ignore if this code region execution time elapses more than 20us.
            // MEMO: 20[us] * (TIMER_RAW_FREQ / 1000000)[count per us]
            // MEMO: then change above using this rule: a/(b/c) = a*1/(b/c) = a*(c/b)
            if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) {
                matrix[row] = matrix_prev[row];
            }

            _delay_us(5);
            KEY_PREV_OFF();
            KEY_UNABLE();

            // NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE.
            // This takes 25us or more to make sure KEY_STATE returns to idle state.
            _delay_us(75);
        }
        if (matrix[row] ^ matrix_prev[row]) matrix_last_modified = timer_read32();
    }
    matrix_power_down();
    return 1;
}

bool matrix_is_modified(void)
{
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        if (matrix[i] != matrix_prev[i])
            return true;
    }
    return false;
}

inline
bool matrix_has_ghost(void)
{
    return false;
}

inline
bool matrix_is_on(uint8_t row, uint8_t col)
{
    return (matrix[row] & (1<<col));
}

inline
matrix_row_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++) {
        xprintf("%02X: %08b\n", row, bitrev(matrix_get_row(row)));
    }
}

void matrix_power_up(void) {
    if (matrix_power) return;
    KEY_POWER_ON();
    matrix_power = true;
}
void matrix_power_down(void) {
    if (!matrix_power) return;
    // doesn't power save while USB connection is active
    if (USB_DeviceState == DEVICE_STATE_Configured) return;
    if (timer_elapsed32(matrix_last_modified) <= MATRIX_POWER_SAVE) return;
    KEY_POWER_OFF();
    suspend_power_down(WDTO_15MS);
    matrix_power = false;
}

M keyboard/infinity/Makefile => keyboard/infinity/Makefile +6 -1
@@ 12,11 12,16 @@ OBJDIR = ./build

OBJECTS = \
	$(OBJDIR)/matrix.o \
	$(OBJDIR)/keymap.o \
	$(OBJDIR)/keymap_common.o \
	$(OBJDIR)/led.o \
	$(OBJDIR)/main.o

ifdef KEYMAP
    OBJECTS := $(OBJDIR)/keymap_$(KEYMAP).o $(OBJECTS)
else
    OBJECTS := $(OBJDIR)/keymap.o $(OBJECTS)
endif

CONFIG_H = config.h

INCLUDE_PATHS = -I.

M keyboard/infinity/config.h => keyboard/infinity/config.h +4 -0
@@ 36,4 36,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
/* key combination for command */
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) 


/* for prototype */
//#define INFINITY_PROTOTYPE

#endif

M keyboard/infinity/keymap.c => keyboard/infinity/keymap.c +2 -1
@@ 20,6 20,7 @@ const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
           LCTL,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,ENT,  \
           LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,RSFT,FN0, \
           NO,  LGUI,LALT,          SPC,                RALT,RGUI,NO, NO),

    /* Layer 1: HHKB mode (HHKB Fn)
     * ,-----------------------------------------------------------.
     * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|


@@ 33,7 34,7 @@ const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
     * |     |Gui|Alt  |         Space         |Alt  |Gui|   |     |
     * `-----------------------------------------------------------'
     */ 
    [1]= 
    [1] = 
    KEYMAP(PWR, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL,   \
           CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS, BSPC,      \
           TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,PENT,            \

M keyboard/infinity/keymap_common.h => keyboard/infinity/keymap_common.h +25 -3
@@ 33,9 33,9 @@ extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
extern const uint16_t fn_actions[];


/* GH60 keymap definition macro
 * K2C, K31 and  K3C are extra keys for ISO
 */
#ifdef INFINITY_PROTOTYPE

/* Infinity prototype */
#define KEYMAP( \
    K00, K10, K20, K30, K40, K50, K60, K70, K80, K01, K11, K21, K31, K41, K86, \
    K51, K61, K71, K81, K02, K12, K22, K32, K42, K52, K62, K72, K82, K03, \


@@ 54,5 54,27 @@ extern const uint16_t fn_actions[];
    { KC_##K80, KC_##K81, KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86 }  \
}

#else

/* Infinity production */
#define KEYMAP( \
    K00, K10, K20, K30, K40, K50, K60, K70, K80, K01, K11, K21, K31, K41, K51, \
    K61, K71, K81, K02, K12, K22, K32, K42, K52, K62, K72, K82, K03, K13, \
    K23, K33, K43, K53, K63, K73, K83, K04, K14, K24, K34, K44, K54, \
    K64, K74, K84, K05, K15, K25, K35, K45, K55, K65, K75, K85, K06, \
    K16, K26, K36,           K46,                K56, K66, K76, K86 \
) { \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06 }, \
    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16 }, \
    { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26 }, \
    { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36 }, \
    { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46 }, \
    { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56 }, \
    { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66 }, \
    { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76 }, \
    { KC_##K80, KC_##K81, KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86 }  \
}

#endif

#endif

A keyboard/nerd/Makefile => keyboard/nerd/Makefile +126 -0
@@ 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 = nerd_lufa

# Directory common source filess exist
TOP_DIR = ../..

# Directory keyboard dependent files exist
TARGET_DIR = .

# project specific files
SRC =	keymap_common.c \
	matrix.c \
	backlight.c

ifdef LAYOUT
   OPT_DEFS += -DNERD_LAYOUT_$(LAYOUT)
endif

ifdef KEYMAP
    SRC := keymap_$(LAYOUT)_$(KEYMAP).c $(SRC)
endif

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)

# 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
#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

# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)

include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk

A keyboard/nerd/README.md => keyboard/nerd/README.md +52 -0
@@ 0,0 1,52 @@
NerD keyboard firmware
========================

Korean Keyboard designed by GON.

*Note that this is not the official firmware*


Hardware revision
-----------------

This firmware was developed and tested for NerD pcb version 1.61 and 2.0.


Supported features
------------------

* All layout options are supported
* All leds are supported
* 60% and 80% (TKL) pcbs are supported


Changing Bootloader
-------------------

You can't simply just upload this firmware to a new NerD board because the original
bootloader won't accept DFU connections.

You can change the bootloader of the keyboard with an ISP programmer of your choice.
The bootloader pins are easy to access on the NerD pcb.

*Be aware that after changing the bootloader the official configuration software
won't work anymore and you'll lose your warrenty. GON won't provide any support for this firmware.*


Build
-----

For building you have to specify two build-options, LAYOUT and KEYMAP. The layout option defines
pcb layout and can be either 60% or 80% at the momemnt. The keymap option selects your
preferred keymapping.

Move to this directory then just run `make LAYOUT=60 KEYMAP=ansi150`

to compile a firmware for a 60% pcb with ANSI 150 key mapping.


Jump to Bootloader
------------------

You can jump to bootloader by software if you have a macro defined for this in your keymap. The
default command is (LSFT+RSFT+PAUS) to access the bootloader by software jump.

A keyboard/nerd/backlight.c => keyboard/nerd/backlight.c +81 -0
@@ 0,0 1,81 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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"
#include "led.h"

void backlight_init_ports()
{
    DDRB |= 0b11100000; // PB7 (switch), PB6 (pcb), PB5 (caps)
}

void led_set(uint8_t usb_led)
{
    (usb_led & (1<<USB_LED_CAPS_LOCK)) ? backlight_caps_enable() : backlight_caps_disable();
}

void backlight_set(uint8_t level)
{
    (level & BACKLIGHT_SWITCH) ? backlight_switch_enable() : backlight_switch_disable();
    (level & BACKLIGHT_PCB) ? backlight_pcb_enable() : backlight_pcb_disable();
}

void backlight_switch_enable()
{
    PORTB |= 0b10000000;
}

void backlight_switch_disable()
{
    PORTB &= ~0b10000000;
}

void backlight_switch_invert()
{
    PORTB ^= 0b10000000;
}

void backlight_pcb_enable()
{
    PORTB |= 0b01000000;
}

void backlight_pcb_disable()
{
    PORTB &= ~0b01000000;
}

void backlight_pcb_invert()
{
    PORTB ^= 0b01000000;
}

void backlight_caps_enable()
{
    PORTB |= 0b00100000;
}

void backlight_caps_disable()
{
    PORTB &= ~0b00100000;
}

void backlight_caps_invert()
{
    PORTB ^= 0b00100000;
}

A keyboard/nerd/backlight.h => keyboard/nerd/backlight.h +40 -0
@@ 0,0 1,40 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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 BACKLIGHT_H
#define BACKLIGHT_H

enum backlight_level {
    BACKLIGHT_SWITCH = 0b0000001,
    BACKLIGHT_PCB    = 0b0000010,
};

void backlight_init_ports(void);

void backlight_switch_invert(void);
void backlight_switch_enable(void);
void backlight_switch_disable(void);

void backlight_pcb_invert(void);
void backlight_pcb_enable(void);
void backlight_pcb_disable(void);

void backlight_caps_invert(void);
void backlight_caps_enable(void);
void backlight_caps_disable(void);

#endif // BACKLIGHT_H

A keyboard/nerd/config.h => keyboard/nerd/config.h +49 -0
@@ 0,0 1,49 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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      0x0001
#define MANUFACTURER    GON
#define PRODUCT         NerD
#define DESCRIPTION     t.m.k. keyboard firmware for NerD

/* key matrix size */
#define MATRIX_ROWS 9
#define MATRIX_COLS 10

/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5

/* number of backlight levels */
#define BACKLIGHT_LEVELS 2

/* 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 */
#define IS_COMMAND() ( \
    keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
)

#endif

A keyboard/nerd/keymap_60_ansi150.c => keyboard/nerd/keymap_60_ansi150.c +30 -0
@@ 0,0 1,30 @@
#include "keymap_common.h"
#include "backlight.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* Layer 0: Default */
    KEYMAP_ANSI150(GRV, 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, \
                   ESC, A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,     ENT,  \
                   LSFT,     Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,RSFT,      \
                   LCTL,LGUI,LALT,          SPC,                          RALT,FN0 ,RCTL),
    /* Layer 1: Space Fn */
    KEYMAP_ANSI150(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,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,     TRNS, \
                   TRNS,     TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,      \
                   TRNS,TRNS,TRNS,          FN1,                          TRNS,FN0, TRNS),
    /* Layer 2: Functions */
    KEYMAP_ANSI150(SLEP,F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, MUTE, \
                   TRNS,BTN1,MS_U,BTN3,PSCR,SLCK,PAUS,HOME,INS, END, MPLY,VOLD,VOLU,FN3,  \
                   CAPS,MS_L,MS_D,MS_R,PGDN,TRNS,LEFT,DOWN,UP  ,RGHT,MPRV,MNXT,     FN2,  \
                   UP,       TRNS,DEL, TRNS,TRNS,PGUP,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,      \
                   LEFT,DOWN,RGHT,          TRNS,                         TRNS,TRNS,TRNS)
};

const uint16_t PROGMEM fn_actions[] = {
    [0] = ACTION_LAYER_MOMENTARY(2),
    [1] = ACTION_LAYER_TAP_KEY(2, KC_SPACE),
    [2] = ACTION_LAYER_TOGGLE(1),
    [3] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_SWITCH)
};

A keyboard/nerd/keymap_80_ansi150.c => keyboard/nerd/keymap_80_ansi150.c +33 -0
@@ 0,0 1,33 @@
#include "keymap_common.h"
#include "backlight.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* Layer 0: Default */
    KEYMAP_ANSI150(ESC,      F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,   PSCR,SLCK,PAUS,  \
                   GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC,  INS, HOME,PGUP,  \
                   TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS,  DEL, END, PGDN,  \
                   CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,     ENT,                    \
                   LSFT,     Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,RSFT,            UP,         \
                   LCTL,LGUI,LALT,               SPC,                     RALT,FN0, RCTL,  LEFT,DOWN,RGHT),
    /* Layer 1: Space Fn */
    KEYMAP_ANSI150(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,  \
                   TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,  TRNS,TRNS,TRNS,  \
                    ESC,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,               FN1,                     TRNS,FN0, TRNS,  TRNS,TRNS,TRNS),
    /* Layer 2: Functions */
    KEYMAP_ANSI150(SLEP,     MYCM,WSCH,WHOM,MAIL,VOLD,VOLU,MUTE,MSEL,MPLY,MPRV,MNXT,MSTP,  TRNS,TRNS,TRNS,  \
                   TRNS,TRNS,TRNS,TRNS,END, TRNS,TRNS,TRNS,TRNS,TRNS,HOME,TRNS,TRNS,TRNS,  TRNS,TRNS,TRNS,  \
                   TRNS,BTN1,MS_U,BTN3,PSCR,SLCK,TRNS,TRNS,INS, TRNS,TRNS,TRNS,TRNS,FN3,   TRNS,TRNS,TRNS,  \
                   CAPS,MS_L,MS_D,MS_R,PGDN,TRNS,LEFT,DOWN,UP  ,RGHT,TRNS,TRNS,     FN2,                    \
                   TRNS,     TRNS,DEL, TRNS,TRNS,PGUP,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,            TRNS,       \
                   TRNS,TRNS,TRNS,               TRNS,                    TRNS,TRNS,TRNS,  TRNS,TRNS,TRNS),
};

const uint16_t PROGMEM fn_actions[] = {
    [0] = ACTION_LAYER_MOMENTARY(2),
    [1] = ACTION_LAYER_TAP_KEY(2, KC_SPACE),
    [2] = ACTION_LAYER_TOGGLE(1),
    [3] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_SWITCH)
};

R keyboard/hhkb_rn42/keymap_common.c => keyboard/nerd/keymap_common.c +1 -5
@@ 1,5 1,5 @@
/*
Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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


@@ 14,12 14,8 @@ 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 "action.h"
#include <avr/pgmspace.h>
#include "keymap_common.h"


/* translates key to keycode */
uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
{

A keyboard/nerd/keymap_common.h => keyboard/nerd/keymap_common.h +89 -0
@@ 0,0 1,89 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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 <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"

extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
extern const uint16_t fn_actions[];

#define KEYMAP( \
        K08,      K09, K18, K19, K28, K29, K38, K39, K48, K49, K58, K59, K68,    K69, K88, K89, \
        K00, K01, K10, K11, K20, K21, K30, K31, K40, K41, K50, K51, K60, K61,    K80, K81, K84, \
        K02, K03, K12, K13, K22, K23, K32, K33, K42, K43, K52, K53, K62, K63,    K82, K83, K85, \
        K04, K14, K15, K24, K25, K34, K35, K44, K45, K54, K55, K64, K71, K65,                   \
        K07, K79, K16, K17, K26, K27, K36, K37, K46, K47, K56, K57, K66, K67,         K86,      \
        K06, K05, K78,                K70,                K72, K73, K74, K75,    K76, K77, K87  \
) { \
      { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09 }, \
      { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19 }, \
      { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29 }, \
      { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39 }, \
      { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47, KC_##K48, KC_##K49 }, \
      { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57, KC_##K58, KC_##K59 }, \
      { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67, KC_##K68, KC_##K69 }, \
      { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77, KC_##K78, KC_##K79 }, \
      { KC_##K80, KC_##K81, KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86, KC_##K87, KC_##K88, KC_##K89 }  \
}

#ifdef NERD_LAYOUT_60
  #define KEYMAP_ANSI150( \
          K08, K01, K10, K11, K20, K21, K30, K31, K40, K41, K50, K51, K60, K61, \
          K02, K03, K12, K13, K22, K23, K32, K33, K42, K43, K52, K53, K62, K63, \
          K04, K14, K15, K24, K25, K34, K35, K44, K45, K54, K55, K64,      K65, \
          K07,      K16, K17, K26, K27, K36, K37, K46, K47, K56, K57, K66,      \
          K06, K05, K78,                K70,                     K73, K74, K75  \
  ) KEYMAP( \
          K08,      NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,   NO,  NO,  NO,  \
          NO,  K01, K10, K11, K20, K21, K30, K31, K40, K41, K50, K51, K60, K61,  NO,  NO,  NO,  \
          K02, K03, K12, K13, K22, K23, K32, K33, K42, K43, K52, K53, K62, K63,  NO,  NO,  NO,  \
          K04, K14, K15, K24, K25, K34, K35, K44, K45, K54, K55, K64, NO,  K65,                 \
          K07, NO,  K16, K17, K26, K27, K36, K37, K46, K47, K56, K57, K66, NO,        NO,       \
          K06, K05, K78,                K70,                NO,  K73, K74, K75,  NO,  NO,  NO   \
  )
#endif

#ifdef NERD_LAYOUT_80
  #define KEYMAP_ANSI150( \
          K08,      K09, K18, K19, K28, K29, K38, K39, K48, K49, K58, K59, K68,  K69, K88, K89, \
          K00, K01, K10, K11, K20, K21, K30, K31, K40, K41, K50, K51, K60, K61,  K80, K81, K84, \
          K02, K03, K12, K13, K22, K23, K32, K33, K42, K43, K52, K53, K62, K63,  K82, K83, K85, \
          K04, K14, K15, K24, K25, K34, K35, K44, K45, K54, K55, K64,      K65,                 \
          K07,      K16, K17, K26, K27, K36, K37, K46, K47, K56, K57, K66,            K86,      \
          K06, K05, K78,                K70,                     K73, K74, K75,  K76, K77, K87  \
  ) KEYMAP( \
          K08,      K09, K18, K19, K28, K29, K38, K39, K48, K49, K58, K59, K68,  K69, K88, K89, \
          K00, K01, K10, K11, K20, K21, K30, K31, K40, K41, K50, K51, K60, K61,  K80, K81, K84, \
          K02, K03, K12, K13, K22, K23, K32, K33, K42, K43, K52, K53, K62, K63,  K82, K83, K85, \
          K04, K14, K15, K24, K25, K34, K35, K44, K45, K54, K55, K64, NO,  K65,                 \
          K07, NO,  K16, K17, K26, K27, K36, K37, K46, K47, K56, K57, K66, NO,        K86,      \
          K06, K05, K78,                K70,                NO,  K73, K74, K75,  K76, K77, K87  \
  )
#endif

#endif // KEYMAP_COMMON_H

A keyboard/nerd/matrix.c => keyboard/nerd/matrix.c +221 -0
@@ 0,0 1,221 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>

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"
#include "backlight.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 uint16_t read_inputs(void);
static void init_inputs(void);
static void init_outputs(void);
static void reset_inputs(void);
static void reset_outputs(void);
static void select_output(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)
{
    backlight_init_ports();
    init_inputs();
    init_outputs();

    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++) {
        reset_inputs();
        reset_outputs();
        select_output(col);
        _delay_us(3);
        uint16_t rows = read_inputs();
        for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
            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;
            }
        }
    }

    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;
}

static void init_inputs(void)
{
    DDRE &= ~0b01000000; // PE6 (Col 0)
    DDRB &= ~0b00001111; // PB0 (Col 1), PB1 (Col 2), PB2 (Col 3), PB3 (Col 4)
    DDRF &= ~0b00000001; // PF0 (Col 5)
    DDRD &= ~0b00100011; // PD0 (Col 6), PD1 (Col 8 TKL), PD5 (Col 7)
}

static uint16_t read_inputs(void)
{
    return (PINE&(1<<6) ? 0 : (1<<0)) |  // PE6 (Col 0)
           (PINB&(1<<0) ? 0 : (1<<1)) |  // PB0 (Col 1)
           (PINB&(1<<1) ? 0 : (1<<2)) |  // PB1 (Col 2)
           (PINB&(1<<2) ? 0 : (1<<3)) |  // PB2 (Col 3)
           (PINB&(1<<3) ? 0 : (1<<4)) |  // PB3 (Col 4)
           (PINF&(1<<0) ? 0 : (1<<5)) |  // PF0 (Col 5)
           (PIND&(1<<0) ? 0 : (1<<6)) |  // PD0 (Col 6)
           (PIND&(1<<5) ? 0 : (1<<7)) |  // PD5 (Col 7)
           (PIND&(1<<1) ? 0 : (1<<8));   // PD1 (Col 8 TKL)
}

static void reset_inputs(void)
{
    PORTE |= 0b01000000; // PE6 (Col 0)
    PORTB |= 0b00001111; // PB0 (Col 1), PB1 (Col 2), PB2 (Col 3), PB3 (Col 4)
    PORTF |= 0b00000001; // PF0 (Col 5)
    PORTD |= 0b00100011; // PD0 (Col 6), PD1 (Col 8 TKL), PD5 (Col 7)
}

static void init_outputs(void)
{
    DDRB |= 0b00010000; // PB4 (Row 0)
    DDRE |= 0b00000100; // PE2 (Row 1)
    DDRF |= 0b11110010; // PF4 (Row 2), PF7 (Row 3), PF1 (Row 4), PF6 (Row 5), PF5 (Row 7)
    DDRC |= 0b11000000; // PC6 (Row 6), PC7 (Row 9)
    DDRD |= 0b10000000; // PD7 (Row 8)
}

static void reset_outputs(void)
{
    PORTB |= 0b00010000; // PB4 (Row 0)
    PORTE |= 0b00000100; // PE2 (Row 1)
    PORTF |= 0b11110010; // PF4 (Row 2), PF7 (Row 3), PF1 (Row 4), PF6 (Row 5), PF5 (Row 7)
    PORTC |= 0b11000000; // PC6 (Row 6), PC7 (Row 9)
    PORTD |= 0b10000000; // PD7 (Row 8)
}

static void select_output(uint8_t col)
{
    switch (col) {
        case 0:
            PORTB &= ~(1<<4);
            break;
        case 1:
            PORTE &= ~(1<<2);
            break;
        case 2:
            PORTF &= ~(1<<4);
            break;
        case 3:
            PORTF &= ~(1<<7);
            break;
        case 4:
            PORTF &= ~(1<<1);
            break;
        case 5:
            PORTF &= ~(1<<6);
            break;
        case 6:
            PORTC &= ~(1<<6);
            break;
        case 7:
            PORTF &= ~(1<<5);
            break;
        case 8:
            PORTD &= ~(1<<7);
            break;
        case 9:
            PORTC &= ~(1<<7);
            break;
    }
}

M protocol/adb.c => protocol/adb.c +1 -1
@@ 360,7 360,7 @@ Commands
    3:  mice

    Registers:
    0: application(keyobard uses this to store its data.)
    0: application(keyboard uses this to store its data.)
    1: application
    2: application(keyboard uses this for LEDs and state of modifiers)
    3: status and command

M protocol/bluefruit/main.c => protocol/bluefruit/main.c +1 -1
@@ 104,7 104,7 @@ int main(void)
        dprintf("Starting main loop");
        while (1) {
            while (suspend) {
                suspend_power_down(WDTO_120MS);
                suspend_power_down();
                if (remote_wakeup && suspend_wakeup_condition()) {
                    usb_remote_wakeup();
                }

M protocol/lufa/lufa.c => protocol/lufa/lufa.c +22 -19
@@ 148,8 148,10 @@ static void Console_Task(void)
*/
void EVENT_USB_Device_Connect(void)
{
    print("[C]");
    /* For battery powered device */
    if (!USB_IsInitialized) {
        USB_Disable();
        USB_Init();
        USB_Device_EnableSOFEvents();
    }


@@ 157,7 159,9 @@ void EVENT_USB_Device_Connect(void)

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. 
    if (USB_IsInitialized) {
        USB_Disable();  // Disable all interrupts


@@ 169,10 173,13 @@ void EVENT_USB_Device_Disconnect(void)

void EVENT_USB_Device_Reset(void)
{
    print("[R]");
}

void EVENT_USB_Device_Suspend()
{
    print("[S]");
    matrix_power_down();
#ifdef SLEEP_LED_ENABLE
    sleep_led_enable();
#endif


@@ 180,6 187,7 @@ void EVENT_USB_Device_Suspend()

void EVENT_USB_Device_WakeUp()
{
    print("[W]");
    suspend_wakeup_init();

#ifdef SLEEP_LED_ENABLE


@@ 489,37 497,28 @@ int8_t sendchar(uint8_t c)
    uint8_t ep = Endpoint_GetCurrentEndpoint();
    Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
    if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
        Endpoint_SelectEndpoint(ep);
        return -1;
        goto ERROR_EXIT;
    }

    if (timeouted && !Endpoint_IsReadWriteAllowed()) {
        Endpoint_SelectEndpoint(ep);
        return - 1;
        goto ERROR_EXIT;
    }

    timeouted = false;

    uint8_t timeout = SEND_TIMEOUT;
    uint16_t prevFN = USB_Device_GetFrameNumber();
    while (!Endpoint_IsReadWriteAllowed()) {
        switch (USB_DeviceState) {
        case DEVICE_STATE_Unattached:
        case DEVICE_STATE_Suspended:
            return -1;
        if (USB_DeviceState != DEVICE_STATE_Configured) {
            goto ERROR_EXIT;
        }
        if (Endpoint_IsStalled()) {
            Endpoint_SelectEndpoint(ep);
            return -1;
            goto ERROR_EXIT;
        }
        if (prevFN != USB_Device_GetFrameNumber()) {
            if (!(timeout--)) {
                timeouted = true;
                Endpoint_SelectEndpoint(ep);
                return -1;
            }
            prevFN = USB_Device_GetFrameNumber();
        if (!(timeout--)) {
            timeouted = true;
            goto ERROR_EXIT;
        }
        _delay_ms(1);
    }

    Endpoint_Write_8(c);


@@ 530,6 529,9 @@ int8_t sendchar(uint8_t c)

    Endpoint_SelectEndpoint(ep);
    return 0;
ERROR_EXIT:
    Endpoint_SelectEndpoint(ep);
    return -1;
}
#else
int8_t sendchar(uint8_t c)


@@ 587,7 589,8 @@ int main(void)
    print("Keyboard start.\n");
    while (1) {
        while (USB_DeviceState == DEVICE_STATE_Suspended) {
            suspend_power_down(WDTO_120MS);
            print("[s]");
            suspend_power_down();
            if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
                    USB_Device_SendRemoteWakeup();
            }

M protocol/pjrc/main.c => protocol/pjrc/main.c +1 -1
@@ 61,7 61,7 @@ int main(void)
#endif
    while (1) {
        while (suspend) {
            suspend_power_down(WDTO_120MS);
            suspend_power_down();
            if (remote_wakeup && suspend_wakeup_condition()) {
                usb_remote_wakeup();
            }