added ergodox
authorEvan Sailer <esailer@asu.edu>
Sat, 7 Jan 2017 17:45:31 +0000 (10:45 -0700)
committerEvan Sailer <esailer@asu.edu>
Sat, 7 Jan 2017 17:45:31 +0000 (10:45 -0700)
18 files changed:
keyboard/ergodox/Ergodox-FAQ.md [new file with mode: 0755]
keyboard/ergodox/Makefile [new file with mode: 0644]
keyboard/ergodox/Makefile.lufa [new file with mode: 0755]
keyboard/ergodox/Makefile.pjrc [new file with mode: 0755]
keyboard/ergodox/config.h [new file with mode: 0755]
keyboard/ergodox/ergodox.c [new file with mode: 0755]
keyboard/ergodox/ergodox.h [new file with mode: 0755]
keyboard/ergodox/i2cmaster.h [new file with mode: 0755]
keyboard/ergodox/keymap_blazak.c [new file with mode: 0755]
keyboard/ergodox/keymap_colemak.c [new file with mode: 0755]
keyboard/ergodox/keymap_common.h [new file with mode: 0755]
keyboard/ergodox/keymap_cub.c [new file with mode: 0755]
keyboard/ergodox/keymap_dvorak.c [new file with mode: 0755]
keyboard/ergodox/keymap_micro.c [new file with mode: 0755]
keyboard/ergodox/keymap_passwords_example.h [new file with mode: 0755]
keyboard/ergodox/led.c [new file with mode: 0755]
keyboard/ergodox/matrix.c [new file with mode: 0755]
keyboard/ergodox/twimaster.c [new file with mode: 0755]

diff --git a/keyboard/ergodox/Ergodox-FAQ.md b/keyboard/ergodox/Ergodox-FAQ.md
new file mode 100755 (executable)
index 0000000..256806a
--- /dev/null
@@ -0,0 +1,72 @@
+# TMK Generic
+
+* I'm not sure what the Magic + H does.
+ Is this a menu that will pop up regardless of what platform and program is open? 
+
+ Yes, this is sort of debugging.
+ Use PJRC's [hid_listen](https://www.pjrc.com/teensy/hid_listen.html) to see debug messages.
+
+# TMK/Ergodox specific
+
+* I would like to configure my leds to indicate the active layer.
+ I read that can be done, but I haven't seen an example for this firmware.
+ Can someone please post an example or a link?
+
+ TMK for Ergodox have support for seven (!) led's:
+ - three on right
+ - three on left (see http://geekhack.org/index.php?topic=22780.msg873819#msg873819 for more details)
+ - Teensy onboard led as well
+
+ Any of these leds can be used as layer indicator or NumLock/CapsLock/ScrollLock led.
+
+ [Here is example](https://github.com/cub-uanic/tmk_keyboard/blob/cub_layout/keyboard/ergodox/matrix.c#L121-167)
+ how you can assign some meaning to each led.
+ In this code only left leds are used to show layers, but you can
+ [change `led_set()`](https://github.com/cub-uanic/tmk_keyboard/blob/cub_layout/keyboard/ergodox/led.c)
+ and do anything you want with all leds.
+
+# Firmware
+
+#### Where to get binaries?
+https://github.com/cub-uanic/tmk_keyboard/releases
+
+#### Where to get sources?
+https://github.com/cub-uanic/tmk_keyboard/tree/master
+
+#### How to compile?
+
+    cd tmk_keyboard/keyboard/ergodox
+
+    # just to be safe
+    make -f Makefile.lufa clean
+
+    # use one of these
+    make -f Makefile.lufa
+    make -f Makefile.lufa dvorak
+    make -f Makefile.lufa colemak
+    make -f Makefile.lufa workman
+    make -f Makefile.lufa micro
+    make -f Makefile.lufa cub
+
+
+# Layouts
+
+TODO description of layouts in base firmware binaries
+
+
+# Things TO-DO
+
+- [ ] Flash NumLock led only when "numpad" layer is active
+- [ ] Command (in terms of IS_COMMAND) to switch to no-leds mode
+- [ ] Increase count of ACTION keys
+- [ ] Fix command_state() onboard led: it should flash only when kbd in some specific mode (CONSOLE || MOUSE)
+- [ ] ergodox_blink_all_leds() should save current state of leds, and restore after blink. initial state of all leds == off
+- [ ] add support for pseudo-backlight (reversed LEDs) + docs/photo
+- [ ] command to debug all LEDs (on/off/blink)
+- [ ] proper (in-core) implementation of DEBUG_MATRIX_SCAN_RATE (non-Ergodox specific)
+- [ ] proper (in-core) support for per-layer fn_actions[]
+- [ ] create one-handed layouts, see
+        http://half-qwerty.com/
+        https://geekhack.org/index.php?topic=60165.0
+        https://www.massdrop.com/ext/ergodox/?hash=e097c3b9932179055023d47e48b25f1d
+
diff --git a/keyboard/ergodox/Makefile b/keyboard/ergodox/Makefile
new file mode 100644 (file)
index 0000000..2562419
--- /dev/null
@@ -0,0 +1,132 @@
+#----------------------------------------------------------------------------
+# 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).
+ifdef TARGETFILE
+       TARGET = $(TARGETFILE)
+else
+       TARGET = ergodox_lufa
+endif
+
+# Directory common source filess exist
+TMK_DIR = ../../tmk_core
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC =  matrix.c \
+       led.c \
+       ergodox.c \
+       twimaster.c
+
+ifdef KEYMAP
+    SRC := keymap_$(KEYMAP).c $(SRC)
+else
+    SRC := keymap_blazak.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+
+# MCU name, you MUST set this to match the board you are using
+# type "make clean" after changing this, so all files will be rebuilt
+MCU = atmega32u4
+#MCU = at90usb1286
+
+
+# Processor frequency.
+#   Normally the first thing your program should do is set the clock prescaler,
+#   so your program will run at the correct speed.  You should also set this
+#   variable to same clock speed.  The _delay_ms() macro uses this, and many
+#   examples use this variable to calculate timings.  Do not add a "UL" here.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+#     This will define a symbol, F_USB, in all source code files equal to the
+#     input clock frequency (before any prescaling is performed) in Hz. This value may
+#     differ from F_CPU if prescaling is used on the latter, and is required as the
+#     raw input clock is fed directly to the PLL sections of the AVR for high speed
+#     clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+#     at the end, this will be done automatically to create a 32-bit value in your
+#     source code.
+#
+#     If no clock division is performed on the input clock inside the AVR (via the
+#     CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+# Boot Section Size in *bytes*
+#   Teensy halfKay   512
+#   Atmel DFU loader 4096
+#   LUFA bootloader  4096
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+# Build Options
+#   comment out to disable the options.
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes  # Mouse keys(+5000)
+EXTRAKEY_ENABLE = yes  # Audio control and System control(+600)
+CONSOLE_ENABLE = yes    # Console for debug
+COMMAND_ENABLE = yes    # Commands for debug and configuration
+SLEEP_LED_ENABLE = yes  # Breathing sleep LED during USB suspend
+NKRO_ENABLE = yes              # USB Nkey Rollover (+500)
+#PS2_MOUSE_ENABLE = yes        # PS/2 mouse(TrackPoint) support
+INVERT_NUMLOCK = yes   # invert state of NumLock led
+
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TMK_DIR)
+
+include $(TMK_DIR)/protocol.mk
+include $(TMK_DIR)/protocol/lufa.mk
+include $(TMK_DIR)/common.mk
+include $(TMK_DIR)/rules.mk
diff --git a/keyboard/ergodox/Makefile.lufa b/keyboard/ergodox/Makefile.lufa
new file mode 100755 (executable)
index 0000000..976877e
--- /dev/null
@@ -0,0 +1,129 @@
+#----------------------------------------------------------------------------
+# 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 = ergodox_lufa
+
+# Directory common source filess exist
+TMK_DIR = ../../tmk_core
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC =  keymap_common.c \
+       matrix.c \
+       led.c \
+       ergodox.c \
+       twimaster.c
+
+ifdef KEYMAP
+    SRC := keymap_$(KEYMAP).c $(SRC)
+else
+    SRC := keymap_blazak.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+
+# MCU name, you MUST set this to match the board you are using
+# type "make clean" after changing this, so all files will be rebuilt
+MCU = atmega32u4
+#MCU = at90usb1286
+
+
+# Processor frequency.
+#   Normally the first thing your program should do is set the clock prescaler,
+#   so your program will run at the correct speed.  You should also set this
+#   variable to same clock speed.  The _delay_ms() macro uses this, and many
+#   examples use this variable to calculate timings.  Do not add a "UL" here.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+#     This will define a symbol, F_USB, in all source code files equal to the
+#     input clock frequency (before any prescaling is performed) in Hz. This value may
+#     differ from F_CPU if prescaling is used on the latter, and is required as the
+#     raw input clock is fed directly to the PLL sections of the AVR for high speed
+#     clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+#     at the end, this will be done automatically to create a 32-bit value in your
+#     source code.
+#
+#     If no clock division is performed on the input clock inside the AVR (via the
+#     CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+# Boot Section Size in *bytes*
+#   Teensy halfKay   512
+#   Atmel DFU loader 4096
+#   LUFA bootloader  4096
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+# Build Options
+#   comment out to disable the options.
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes  # Mouse keys(+5000)
+EXTRAKEY_ENABLE = yes  # Audio control and System control(+600)
+CONSOLE_ENABLE = yes    # Console for debug
+COMMAND_ENABLE = yes    # Commands for debug and configuration
+SLEEP_LED_ENABLE = yes  # Breathing sleep LED during USB suspend
+NKRO_ENABLE = yes              # USB Nkey Rollover (+500)
+#PS2_MOUSE_ENABLE = yes        # PS/2 mouse(TrackPoint) support
+INVERT_NUMLOCK = yes   # invert state of NumLock led
+
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TMK_DIR)
+
+include $(TMK_DIR)/protocol.mk
+include $(TMK_DIR)/protocol/lufa.mk
+include $(TMK_DIR)/common.mk
+include $(TMK_DIR)/rules.mk
diff --git a/keyboard/ergodox/Makefile.pjrc b/keyboard/ergodox/Makefile.pjrc
new file mode 100755 (executable)
index 0000000..04b07d9
--- /dev/null
@@ -0,0 +1,108 @@
+#----------------------------------------------------------------------------
+# 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 = ergodox_pjrc
+
+# Directory common source filess exist
+TMK_DIR = ../../tmk_core
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC =  keymap_common.c \
+       matrix.c \
+       led.c \
+       ergodox.c \
+       twimaster.c
+
+ifdef KEYMAP
+    SRC := keymap_$(KEYMAP).c $(SRC)
+else
+    SRC := keymap_blazak.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+
+# MCU name, you MUST set this to match the board you are using
+# type "make clean" after changing this, so all files will be rebuilt
+MCU = atmega32u4
+#MCU = at90usb1286
+
+
+# Processor frequency.
+#   Normally the first thing your program should do is set the clock prescaler,
+#   so your program will run at the correct speed.  You should also set this
+#   variable to same clock speed.  The _delay_ms() macro uses this, and many
+#   examples use this variable to calculate timings.  Do not add a "UL" here.
+F_CPU = 16000000
+
+
+# Boot Section Size in *bytes*
+#   Teensy halfKay   512
+#   Atmel DFU loader 4096
+#   LUFA bootloader  4096
+OPT_DEFS += -DBOOTLOADER_SIZE=512 -DFLASH_SIZE_BYTES=0x8000
+
+
+# Build Options
+#   comment out to disable the options.
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes  # Mouse keys(+5000)
+EXTRAKEY_ENABLE = yes  # Audio control and System control(+600)
+CONSOLE_ENABLE = yes    # Console for debug
+COMMAND_ENABLE = yes    # Commands for debug and configuration
+SLEEP_LED_ENABLE = yes  # Breathing sleep LED during USB suspend
+NKRO_ENABLE = yes              # USB Nkey Rollover (+500)
+#PS2_MOUSE_ENABLE = yes        # PS/2 mouse(TrackPoint) support
+INVERT_NUMLOCK = yes   # invert state of NumLock led
+
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TMK_DIR)
+
+include $(TMK_DIR)/protocol.mk
+include $(TMK_DIR)/protocol/pjrc.mk
+include $(TMK_DIR)/common.mk
+include $(TMK_DIR)/rules.mk
diff --git a/keyboard/ergodox/config.h b/keyboard/ergodox/config.h
new file mode 100755 (executable)
index 0000000..191efa4
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+Copyright 2013 Oleg Kostyuk <cub.uanic@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/>.
+
+
+This work is heavily based on initial firmware for Ergodox keyboard.
+Copyright (c) 2012, 2013 Ben Blazak <benblazak.dev@gmail.com>
+Released under The MIT License (see "doc/licenses/MIT.md")
+Project located at <https://github.com/benblazak/ergodox-firmware>
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID       0xFEED
+#define PRODUCT_ID      0x1307
+#define DEVICE_VER      0x0001
+#define MANUFACTURER    TMK/Cub
+#define PRODUCT         Ergodox
+#define DESCRIPTION     t.m.k. keyboard firmware for Ergodox
+
+#define MATRIX_ROWS 14
+#define MATRIX_COLS 6
+
+#define MOUSEKEY_DELAY          100
+#define MOUSEKEY_INTERVAL       20
+#define MOUSEKEY_MAX_SPEED      3
+#define MOUSEKEY_TIME_TO_MAX    10
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+/*
+ * This constant define not debouncing time in msecs, but amount of matrix
+ * scan loops which should be made to get stable debounced results.
+ *
+ * On Ergodox matrix scan rate is relatively low, because of slow I2C.
+ * Now it's only 317 scans/second, or about 3.15 msec/scan.
+ * According to Cherry specs, debouncing time is 5 msec.
+ *
+ * And so, there is no sense to have DEBOUNCE higher than 2.
+ */
+#define DEBOUNCE        2
+#define TAPPING_TERM    230
+
+/* 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_LCTL) | MOD_BIT(KC_RCTL)) || \
+    keyboard_report->mods == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
+)
+
+
+
+/*
+ * Feature disable options
+ *  These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+//#define DEBUG_MATRIX_SCAN_RATE
+
+#endif
diff --git a/keyboard/ergodox/ergodox.c b/keyboard/ergodox/ergodox.c
new file mode 100755 (executable)
index 0000000..a88772c
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+Copyright 2013 Oleg Kostyuk <cub.uanic@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/>.
+
+
+This work is heavily based on initial firmware for Ergodox keyboard.
+Copyright (c) 2012, 2013 Ben Blazak <benblazak.dev@gmail.com>
+Released under The MIT License (see "doc/licenses/MIT.md")
+Project located at <https://github.com/benblazak/ergodox-firmware>
+
+Most used files are located at
+<https://github.com/benblazak/ergodox-firmware/tree/partial-rewrite/firmware/keyboard/ergodox/controller>
+
+*/
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "action.h"
+#include "command.h"
+#include "print.h"
+#include "debug.h"
+#include "ergodox.h"
+#include "i2cmaster.h"
+
+bool i2c_initialized = 0;
+uint8_t mcp23018_status = 0x20;
+
+bool ergodox_left_led_1 = 0;  // left top
+bool ergodox_left_led_2 = 0;  // left middle
+bool ergodox_left_led_3 = 0;  // left bottom
+
+
+void init_ergodox(void)
+{
+    // keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
+    TCCR1A = 0b10101001;  // set and configure fast PWM
+    TCCR1B = 0b00001001;  // set and configure fast PWM
+
+    // (tied to Vcc for hardware convenience)
+    DDRB  &= ~(1<<4);  // set B(4) as input
+    PORTB &= ~(1<<4);  // set B(4) internal pull-up disabled
+
+    // unused pins - C7, D4, D5, D7, E6
+    // set as input with internal pull-ip enabled
+    DDRC  &= ~(1<<7);
+    DDRD  &= ~(1<<7 | 1<<5 | 1<<4);
+    DDRE  &= ~(1<<6);
+    PORTC |=  (1<<7);
+    PORTD |=  (1<<7 | 1<<5 | 1<<4);
+    PORTE |=  (1<<6);
+}
+
+void ergodox_blink_all_leds(void)
+{
+    ergodox_led_all_off();
+    ergodox_led_all_set(LED_BRIGHTNESS_HI);
+    ergodox_led_all_on();
+    _delay_ms(333);
+    ergodox_led_all_off();
+}
+
+uint8_t init_mcp23018(void) {
+    mcp23018_status = 0x20;
+
+    // I2C subsystem
+    if (i2c_initialized == 0) {
+        i2c_init();  // on pins D(1,0)
+        i2c_initialized++;
+        _delay_ms(1000);
+    }
+
+    // set pin direction
+    // - unused  : input  : 1
+    // - input   : input  : 1
+    // - driving : output : 0
+    mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(IODIRA);            if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(0b00000000);        if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(0b00111111);        if (mcp23018_status) goto out;
+    i2c_stop();
+
+    // set pull-up
+    // - unused  : on  : 1
+    // - input   : on  : 1
+    // - driving : off : 0
+    mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(GPPUA);             if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(0b00000000);        if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(0b00111111);        if (mcp23018_status) goto out;
+
+out:
+    i2c_stop();
+
+    if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update();
+
+    return mcp23018_status;
+}
+
+uint8_t ergodox_left_leds_update(void) {
+    if (mcp23018_status) { // if there was an error
+        return mcp23018_status;
+    }
+
+    // set logical value (doesn't matter on inputs)
+    // - unused  : hi-Z : 1
+    // - input   : hi-Z : 1
+    // - driving : hi-Z : 1
+    mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(OLATA);             if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(0b11111111
+            & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
+          );                                        if (mcp23018_status) goto out;
+    mcp23018_status = i2c_write(0b11111111
+            & ~(ergodox_left_led_2<<LEFT_LED_2_SHIFT)
+            & ~(ergodox_left_led_1<<LEFT_LED_1_SHIFT)
+          );                                        if (mcp23018_status) goto out;
+
+out:
+    i2c_stop();
+    return mcp23018_status;
+}
diff --git a/keyboard/ergodox/ergodox.h b/keyboard/ergodox/ergodox.h
new file mode 100755 (executable)
index 0000000..460d995
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+Copyright 2013 Oleg Kostyuk <cub.uanic@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/>.
+
+
+Copyright (c) 2012, 2013 Ben Blazak <benblazak.dev@gmail.com>
+Released under The MIT License (see "doc/licenses/MIT.md")
+Project located at <https://github.com/benblazak/ergodox-firmware>
+
+Most used files are located at
+<https://github.com/benblazak/ergodox-firmware/tree/partial-rewrite/firmware/keyboard/ergodox/controller>
+
+*/
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include "i2cmaster.h"
+
+#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+#define CPU_16MHz       0x00
+
+// I2C aliases and register addresses (see "mcp23018.md")
+#define I2C_ADDR        0b0100000
+#define I2C_ADDR_WRITE  ( (I2C_ADDR<<1) | I2C_WRITE )
+#define I2C_ADDR_READ   ( (I2C_ADDR<<1) | I2C_READ  )
+#define IODIRA          0x00            // i/o direction register
+#define IODIRB          0x01
+#define GPPUA           0x0C            // GPIO pull-up resistor register
+#define GPPUB           0x0D
+#define GPIOA           0x12            // general purpose i/o port register (write modifies OLAT)
+#define GPIOB           0x13
+#define OLATA           0x14            // output latch register
+#define OLATB           0x15
+
+extern uint8_t mcp23018_status;
+
+void init_ergodox(void);
+void ergodox_blink_all_leds(void);
+uint8_t init_mcp23018(void);
+uint8_t ergodox_left_leds_update(void);
+
+#define LED_BRIGHTNESS_LO       31
+#define LED_BRIGHTNESS_HI       255
+
+#define LEFT_LED_1_SHIFT        7       // in MCP23018 port B
+#define LEFT_LED_2_SHIFT        6       // in MCP23018 port B
+#define LEFT_LED_3_SHIFT        7       // in MCP23018 port A
+
+extern bool ergodox_left_led_1;         // left top
+extern bool ergodox_left_led_2;         // left middle
+extern bool ergodox_left_led_3;         // left bottom
+
+inline void ergodox_board_led_on(void)      { DDRD |=  (1<<6); PORTD |=  (1<<6); }
+inline void ergodox_right_led_1_on(void)    { DDRB |=  (1<<5); PORTB |=  (1<<5); }
+inline void ergodox_right_led_2_on(void)    { DDRB |=  (1<<6); PORTB |=  (1<<6); }
+inline void ergodox_right_led_3_on(void)    { DDRB |=  (1<<7); PORTB |=  (1<<7); }
+inline void ergodox_left_led_1_on(void)     { ergodox_left_led_1 = 1; }
+inline void ergodox_left_led_2_on(void)     { ergodox_left_led_2 = 1; }
+inline void ergodox_left_led_3_on(void)     { ergodox_left_led_3 = 1; }
+
+inline void ergodox_board_led_off(void)     { DDRD &= ~(1<<6); PORTD &= ~(1<<6); }
+inline void ergodox_right_led_1_off(void)   { DDRB &= ~(1<<5); PORTB &= ~(1<<5); }
+inline void ergodox_right_led_2_off(void)   { DDRB &= ~(1<<6); PORTB &= ~(1<<6); }
+inline void ergodox_right_led_3_off(void)   { DDRB &= ~(1<<7); PORTB &= ~(1<<7); }
+inline void ergodox_left_led_1_off(void)    { ergodox_left_led_1 = 0; }
+inline void ergodox_left_led_2_off(void)    { ergodox_left_led_2 = 0; }
+inline void ergodox_left_led_3_off(void)    { ergodox_left_led_3 = 0; }
+
+inline void ergodox_led_all_on(void)
+{
+    ergodox_board_led_on();
+    ergodox_right_led_1_on();
+    ergodox_right_led_2_on();
+    ergodox_right_led_3_on();
+    ergodox_left_led_1_on();
+    ergodox_left_led_2_on();
+    ergodox_left_led_3_on();
+    ergodox_left_leds_update();
+}
+
+inline void ergodox_led_all_off(void)
+{
+    ergodox_board_led_off();
+    ergodox_right_led_1_off();
+    ergodox_right_led_2_off();
+    ergodox_right_led_3_off();
+    ergodox_left_led_1_off();
+    ergodox_left_led_2_off();
+    ergodox_left_led_3_off();
+    ergodox_left_leds_update();
+}
+
+inline void ergodox_right_led_1_set(uint8_t n)    { OCR1A = n; }
+inline void ergodox_right_led_2_set(uint8_t n)    { OCR1B = n; }
+inline void ergodox_right_led_3_set(uint8_t n)    { OCR1C = n; }
+
+inline void ergodox_led_all_set(uint8_t n)
+{
+    ergodox_right_led_1_set(n);
+    ergodox_right_led_2_set(n);
+    ergodox_right_led_3_set(n);
+}
+
diff --git a/keyboard/ergodox/i2cmaster.h b/keyboard/ergodox/i2cmaster.h
new file mode 100755 (executable)
index 0000000..3917b9e
--- /dev/null
@@ -0,0 +1,178 @@
+#ifndef _I2CMASTER_H
+#define _I2CMASTER_H   1
+/************************************************************************* 
+* Title:    C include file for the I2C master interface 
+*           (i2cmaster.S or twimaster.c)
+* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
+* File:     $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
+* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
+* Target:   any AVR device
+* Usage:    see Doxygen manual
+**************************************************************************/
+
+#ifdef DOXYGEN
+/**
+ @defgroup pfleury_ic2master I2C Master library
+ @code #include <i2cmaster.h> @endcode
+  
+ @brief I2C (TWI) Master Software Library
+
+ Basic routines for communicating with I2C slave devices. This single master 
+ implementation is limited to one bus master on the I2C bus. 
+
+ This I2c library is implemented as a compact assembler software implementation of the I2C protocol 
+ which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
+ Since the API for these two implementations is exactly the same, an application can be linked either against the
+ software I2C implementation or the hardware I2C implementation.
+
+ Use 4.7k pull-up resistor on the SDA and SCL pin.
+ Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module 
+ i2cmaster.S to your target when using the software I2C implementation ! 
+ Adjust the  CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.
+
+ @note 
+    The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted 
+    to GNU assembler and AVR-GCC C call interface.
+    Replaced the incorrect quarter period delays found in AVR300 with 
+    half period delays. 
+    
+ @author Peter Fleury pfleury@gmx.ch  http://jump.to/fleury
+
+ @par API Usage Example
+  The following code shows typical usage of this library, see example test_i2cmaster.c
+
+ @code
+
+ #include <i2cmaster.h>
+
+
+ #define Dev24C02  0xA2      // device address of EEPROM 24C02, see datasheet
+
+ int main(void)
+ {
+     unsigned char ret;
+
+     i2c_init();                             // initialize I2C library
+
+     // write 0x75 to EEPROM address 5 (Byte Write) 
+     i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
+     i2c_write(0x05);                        // write address = 5
+     i2c_write(0x75);                        // write value 0x75 to EEPROM
+     i2c_stop();                             // set stop conditon = release bus
+
+
+     // read previously written value back from EEPROM address 5 
+     i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
+
+     i2c_write(0x05);                        // write address = 5
+     i2c_rep_start(Dev24C02+I2C_READ);       // set device address and read mode
+
+     ret = i2c_readNak();                    // read one byte from EEPROM
+     i2c_stop();
+
+     for(;;);
+ }
+ @endcode
+
+*/
+#endif /* DOXYGEN */
+
+/**@{*/
+
+#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
+#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
+#endif
+
+#include <avr/io.h>
+
+/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
+#define I2C_READ    1
+
+/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
+#define I2C_WRITE   0
+
+
+/**
+ @brief initialize the I2C master interace. Need to be called only once 
+ @param  void
+ @return none
+ */
+extern void i2c_init(void);
+
+
+/** 
+ @brief Terminates the data transfer and releases the I2C bus 
+ @param void
+ @return none
+ */
+extern void i2c_stop(void);
+
+
+/** 
+ @brief Issues a start condition and sends address and transfer direction 
+  
+ @param    addr address and transfer direction of I2C device
+ @retval   0   device accessible 
+ @retval   1   failed to access device 
+ */
+extern unsigned char i2c_start(unsigned char addr);
+
+
+/**
+ @brief Issues a repeated start condition and sends address and transfer direction 
+
+ @param   addr address and transfer direction of I2C device
+ @retval  0 device accessible
+ @retval  1 failed to access device
+ */
+extern unsigned char i2c_rep_start(unsigned char addr);
+
+
+/**
+ @brief Issues a start condition and sends address and transfer direction 
+   
+ If device is busy, use ack polling to wait until device ready 
+ @param    addr address and transfer direction of I2C device
+ @return   none
+ */
+extern void i2c_start_wait(unsigned char addr);
+
+/**
+ @brief Send one byte to I2C device
+ @param    data  byte to be transfered
+ @retval   0 write successful
+ @retval   1 write failed
+ */
+extern unsigned char i2c_write(unsigned char data);
+
+
+/**
+ @brief    read one byte from the I2C device, request more data from device 
+ @return   byte read from I2C device
+ */
+extern unsigned char i2c_readAck(void);
+
+/**
+ @brief    read one byte from the I2C device, read is followed by a stop condition 
+ @return   byte read from I2C device
+ */
+extern unsigned char i2c_readNak(void);
+
+/** 
+ @brief    read one byte from the I2C device
+ Implemented as a macro, which calls either i2c_readAck or i2c_readNak
+ @param    ack 1 send ack, request more data from device<br>
+               0 send nak, read is followed by a stop condition 
+ @return   byte read from I2C device
+ */
+extern unsigned char i2c_read(unsigned char ack);
+#define i2c_read(ack)  (ack) ? i2c_readAck() : i2c_readNak(); 
+
+
+/**@}*/
+#endif
diff --git a/keyboard/ergodox/keymap_blazak.c b/keyboard/ergodox/keymap_blazak.c
new file mode 100755 (executable)
index 0000000..2a8164c
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+Copyright 2013 Oleg Kostyuk <cub.uanic@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 <util/delay.h>
+#include "bootloader.h"
+#include "keymap_common.h"
+
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+    KEYMAP(  // layer 0 : default
+        // left hand
+        EQL, 1,   2,   3,   4,   5,   ESC,
+        BSLS,Q,   W,   E,   R,   T,   FN2,
+        TAB, A,   S,   D,   F,   G,
+        LSFT,Z,   X,   C,   V,   B,   FN1,
+        LGUI,GRV, BSLS,LEFT,RGHT,
+                                      LCTL,LALT,
+                                           HOME,
+                                 BSPC,DEL, END,
+        // right hand
+             FN3, 6,   7,   8,   9,   0,   MINS,
+             LBRC,Y,   U,   I,   O,   P,   RBRC,
+                  H,   J,   K,   L,   SCLN,QUOT,
+             FN1, N,   M,   COMM,DOT, SLSH,RSFT,
+                       LEFT,DOWN,UP,  RGHT,RGUI,
+        RALT,RCTL,
+        PGUP,
+        PGDN,ENT, SPC
+    ),
+
+    KEYMAP(  // layer 1 : function and symbol keys
+        // left hand
+        TRNS,F1,  F2,  F3,  F4,  F5,  F11,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN4,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             F12, F6,  F7,  F8,  F9,  F10, 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
+    ),
+
+    KEYMAP(  // layer 2 : keyboard functions
+        // left hand
+        FN0, 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,
+        // right hand
+             FN4, 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
+    ),
+
+    KEYMAP(  // layer 3: numpad
+        // left hand
+        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,
+        // right hand
+             TRNS,NLCK,PSLS,PAST,PAST,PMNS,BSPC,
+             TRNS,NO,  P7,  P8,  P9,  PMNS,BSPC,
+                  NO,  P4,  P5,  P6,  PPLS,PENT,
+             TRNS,NO,  P1,  P2,  P3,  PPLS,PENT,
+                       P0,  PDOT,SLSH,PENT,PENT,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+};
+
+/* id for user defined functions */
+enum function_id {
+    TEENSY_KEY,
+};
+
+/*
+ * Fn action definition
+ */
+const uint16_t PROGMEM fn_actions[] = {
+    ACTION_FUNCTION(TEENSY_KEY),                    // FN0 - Teensy key
+    ACTION_LAYER_MOMENTARY(1),                      // FN1 - switch to Layer1
+    ACTION_LAYER_SET(2, ON_PRESS),                  // FN2 - set Layer2
+    ACTION_LAYER_TOGGLE(3),                         // FN3 - toggle Layer3 aka Numpad layer
+    ACTION_LAYER_SET(0, ON_PRESS),                  // FN4 - set Layer0
+};
+
+void action_function(keyrecord_t *event, uint8_t id, uint8_t opt)
+{
+    if (id == TEENSY_KEY) {
+        clear_keyboard();
+        print("\n\nJump to bootloader... ");
+        _delay_ms(250);
+        bootloader_jump(); // should not return
+        print("not supported.\n");
+    }
+}
diff --git a/keyboard/ergodox/keymap_colemak.c b/keyboard/ergodox/keymap_colemak.c
new file mode 100755 (executable)
index 0000000..8ddd51c
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+Copyright 2016 Paul Williamson <squarefrog@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 <util/delay.h>
+#include "bootloader.h"
+#include "keymap_common.h"
+
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+    /*
+     * Keymap 0: Default Colemak Layer
+     *
+     * This is a general purpose Colemak layout which should serve as a good
+     * basis for your own custom layout. Mac users may want to swap the
+     * position of the Alt and GUI keys.
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |  Esc   |   1  |   2  |   3  |   4  |   5  |  ~   |           |  -   |   6  |   7  |   8  |   9  |   0  |   +    |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * |  Tab   |   Q  |   W  |   F  |   P  |   G  |  [   |           |  ]   |   J  |   L  |   U  |   Y  |   ;  |   \    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | CpsLk  |   A  |   R  |   S  |   T  |   D  |------|           |------|   H  |   N  |   E  |   I  |   O  |   '    |
+     * |--------+------+------+------+------+------| +L2  |           |      |------+------+------+------+------+--------|
+     * | LShift |   Z  |   X  |   C  |   V  |   B  |      |           |      |   K  |   M  |   ,  |   .  |   /  | RShift |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   | LCtrl| LGui | LAlt | Left | Rght |                                       |  Up  |  Dn  | RAlt | RGui | RCtrl |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |CpsLck| Del  |       | PgUp | PgDn |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      | LAlt |       | RAlt |      |      |
+     *                                 | BkSp | ~L1  |------|       |------| Enter| Space|
+     *                                 |      |      | LCtrl|       | RCtrl|      |      |
+     *                                 `--------------------'       `--------------------'
+     */
+
+    KEYMAP(
+        // left hand
+        ESC, 1,   2,   3,   4,   5,   GRV,
+        TAB, Q,   W,   F,   P,   G,   LBRC,
+        CAPS,A,   R,   S,   T,   D,
+        LSFT,Z,   X,   C,   V,   B,   FN2,
+        LCTL,LGUI,LALT,LEFT,RGHT,
+                                      CAPS,DEL,
+                                           LALT,
+                                 BSPC,FN1, LCTL,
+        // right hand
+             MINS,6,   7,   8,   9,   0,   EQL,
+             RBRC,J,   L,   U,   Y,   SCLN,BSLS,
+                  H,   N,   E,   I,   O,   QUOT,
+             NO,  K,   M,   COMM,DOT, SLSH,RSFT,
+                       UP,  DOWN,RALT,RGUI,RCTL,
+        PGUP,PGDN,
+        RALT,
+        RCTL,ENT, SPC
+    ),
+
+    /*
+     * Layer 1: Function keys
+     *
+     * This layer contains function keys, and media keys. Additionally, there
+     * are QWERTY-style Vim arrow keys. I could never get used to Colemak's
+     * rearranged Vim arrow placements.
+     *
+     * Most of the non-modifier keys are marked as NO, so it's immediately
+     * obvious if you start typing on a secondary layer.
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * | Teensy |  F1  |  F2  |  F3  |  F4  |  F5  |  F11 |           |  F12 |  F6  |  F7  |  F8  |  F9  |  F10 |  TRNS  |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * |   TRNS |      |      |      |      |      | TRNS |           | TRNS |      |      |      |      |      |  TRNS  |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * |   TRNS |      |      |      |      |      |------|           |------| Left | Down |  Up  | Right|      |  TRNS  |
+     * |--------+------+------+------+------+------| +L2  |           |      |------+------+------+------+------+--------|
+     * |   TRNS |      |      |      |      |      |      |           |      |      |      |      |      |      |  TRNS  |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   | TRNS | TRNS | Play |  RW  |  FF  |                                       | Mute | Vol- | Vol+ | TRNS | TRNS |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |      |      |       | HOME |  END |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      | TRNS |       | TRNS |      |      |
+     *                                 | TRNS |      |------|       |------| TRNS | TRNS |
+     *                                 |      |      | TRNS |       | TRNS |      |      |
+     *                                 `--------------------'       `--------------------'
+     */
+
+    KEYMAP(
+        // left hand
+        FN31,F1,  F2,  F3,  F4,  F5,  F11,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  FN2,
+        TRNS,TRNS,MPLY,MPRV,MNXT,
+                                      NO,  NO,
+                                           TRNS,
+                                 TRNS,NO,  TRNS,
+        // right hand
+             F12, F6,  F7,  F8,  F9,  F10, TRNS,
+             TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+                  LEFT,DOWN,UP,  RGHT,NO,  TRNS,
+             NO,  NO,  NO,  NO,  NO,  NO,  TRNS,
+                       MUTE,VOLD,VOLU,TRNS,TRNS,
+        HOME,END,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    /*
+    * Layer 2: Number Pad
+    *
+    * This layer has a number pad for quicker number entry. As with layer 1,
+    * most of the non-modifier keys are marked as NO, so it's immediately
+    * obvious if you start typing on a secondary layer.
+    *
+    * Inspired by Ben Blazak QWERTY num pad.
+    * https://git.io/voIeY
+    *
+    * ,--------------------------------------------------.           ,--------------------------------------------------.
+    * |   ESC  |      |      |      |      |      |      |           |      |      | NmLk |   /  |   *  |   -  | Bkspc  |
+    * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+    * |   TRNS |      |      |      |      |      | TRNS |           | TRNS |      |   7  |   8  |   9  |   +  | Bkspc  |
+    * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+    * |   TRNS |      |      |      |      |      |------|           |------|      |   4  |   5  |   6  |   +  | Enter  |
+    * |--------+------+------+------+------+------|      |           | -L0  |------+------+------+------+------+--------|
+    * |   TRNS |      |      |      |      |      |      |           |      |      |   1  |   2  |   3  | Enter| Enter  |
+    * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+    *   | TRNS | TRNS | LALT |      |      |                                       |   0  |   0  |   .  | Enter| Enter|
+    *   `----------------------------------'                                       `----------------------------------'
+    *                                        ,-------------.       ,-------------.
+    *                                        |      |      |       | TRNS | TRNS |
+    *                                 ,------|------|------|       |------+------+------.
+    *                                 |      |      | TRNS |       | TRNS |      |      |
+    *                                 | Bkspc|      |------|       |------| Enter|      |
+    *                                 |      |      | TRNS |       | TRNS |      |      |
+    *                                 `--------------------'       `--------------------'
+    */
+
+    KEYMAP(
+        // left hand
+        ESC, NO,  NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  NO,
+        TRNS,TRNS,LALT,NO,  NO,
+                                      NO,  NO,
+                                           TRNS,
+                                 BSPC,NO,  TRNS,
+        // right hand
+             NO,  NO,  NLCK,SLSH,PAST,PMNS,BSPC,
+             TRNS,NO,  P7,  P8,  P9,  PPLS,BSPC,
+                  NO,  P4,  P5,  P6,  PPLS,PENT,
+             FN0, NO,  P1,  P2,  P3,  PENT,PENT,
+                       P0,  P0,  PDOT,PENT,PENT,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,ENT, TRNS
+    ),
+};
+
+/* id for user defined functions */
+enum function_id {
+    TEENSY_KEY,
+};
+
+/*
+ * Fn action definition
+ */
+const uint16_t PROGMEM fn_actions[] = {
+    // Layer shifting
+    [0] = ACTION_LAYER_SET(0, ON_PRESS),           // Switch to Layer 0
+    [1] = ACTION_LAYER_MOMENTARY(1),               // Momentarily switch to layer 1
+    [2] = ACTION_LAYER_SET(2, ON_PRESS),           // Switch to Layer 2
+
+    // Teensy
+    [31] = ACTION_FUNCTION(TEENSY_KEY),
+};
+
+void action_function(keyrecord_t *event, uint8_t id, uint8_t opt)
+{
+    if (id == TEENSY_KEY) {
+        clear_keyboard();
+        print("\n\nJump to bootloader... ");
+        _delay_ms(250);
+        bootloader_jump(); // should not return
+        print("not supported.\n");
+    }
+}
+
diff --git a/keyboard/ergodox/keymap_common.h b/keyboard/ergodox/keymap_common.h
new file mode 100755 (executable)
index 0000000..9ed91bb
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
+Copyright 2016 Mark Sikora <marknsikora@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 <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"
+
+
+/* ErgoDox keymap definition macro */
+#define KEYMAP(                                                 \
+                                                                \
+    /* left hand, spatial positions */                          \
+    k00,k01,k02,k03,k04,k05,k06,                                \
+    k10,k11,k12,k13,k14,k15,k16,                                \
+    k20,k21,k22,k23,k24,k25,                                    \
+    k30,k31,k32,k33,k34,k35,k36,                                \
+    k40,k41,k42,k43,k44,                                        \
+                            k55,k56,                            \
+                                k54,                            \
+                        k53,k52,k51,                            \
+                                                                \
+    /* right hand, spatial positions */                         \
+        k07,k08,k09,k0A,k0B,k0C,k0D,                            \
+        k17,k18,k19,k1A,k1B,k1C,k1D,                            \
+            k28,k29,k2A,k2B,k2C,k2D,                            \
+        k37,k38,k39,k3A,k3B,k3C,k3D,                            \
+                k49,k4A,k4B,k4C,k4D,                            \
+    k57,k58,                                                    \
+    k59,                                                        \
+    k5C,k5B,k5A )                                               \
+                                                                \
+   /* matrix positions */                                       \
+   {                                                            \
+    { KC_##k00,KC_##k10,KC_##k20,KC_##k30,KC_##k40,KC_NO   },   \
+    { KC_##k01,KC_##k11,KC_##k21,KC_##k31,KC_##k41,KC_##k51},   \
+    { KC_##k02,KC_##k12,KC_##k22,KC_##k32,KC_##k42,KC_##k52},   \
+    { KC_##k03,KC_##k13,KC_##k23,KC_##k33,KC_##k43,KC_##k53},   \
+    { KC_##k04,KC_##k14,KC_##k24,KC_##k34,KC_##k44,KC_##k54},   \
+    { KC_##k05,KC_##k15,KC_##k25,KC_##k35,KC_NO,   KC_##k55},   \
+    { KC_##k06,KC_##k16,KC_NO,   KC_##k36,KC_NO,   KC_##k56},   \
+                                                                \
+    { KC_##k07,KC_##k17,KC_NO,   KC_##k37,KC_NO,   KC_##k57},   \
+    { KC_##k08,KC_##k18,KC_##k28,KC_##k38,KC_NO,   KC_##k58},   \
+    { KC_##k09,KC_##k19,KC_##k29,KC_##k39,KC_##k49,KC_##k59},   \
+    { KC_##k0A,KC_##k1A,KC_##k2A,KC_##k3A,KC_##k4A,KC_##k5A},   \
+    { KC_##k0B,KC_##k1B,KC_##k2B,KC_##k3B,KC_##k4B,KC_##k5B},   \
+    { KC_##k0C,KC_##k1C,KC_##k2C,KC_##k3C,KC_##k4C,KC_##k5C},   \
+    { KC_##k0D,KC_##k1D,KC_##k2D,KC_##k3D,KC_##k4D,KC_NO   }    \
+   }
+
+#endif
diff --git a/keyboard/ergodox/keymap_cub.c b/keyboard/ergodox/keymap_cub.c
new file mode 100755 (executable)
index 0000000..aba7c79
--- /dev/null
@@ -0,0 +1,602 @@
+#include <util/delay.h>
+#include "action_layer.h"
+#include "action_util.h"
+#include "bootloader.h"
+#include "keymap_common.h"
+
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+    /*
+     * Keymap: Default Layer in QWERTY
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |   ~    |   1  |   2  |   3  |   4  |   5  |   \  |           |   -  |   6  |   7  |   8  |   9  |   0  |   =    |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   Q  |   W  |   E  |   R  |   T  | ~L5  |           | ~L6  |   Y  |   U  |   I  |   O  |   P  |   [    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | Tab/Shf|   A  |   S  |   D  |   F  |   G  |------|           |------|   H  |   J  |   K  |   L  |   ;  |   '    |
+     * |--------+------+------+------+------+------|  L0  |           | ~L7  |------+------+------+------+------+--------|
+     * | LCtrl  |   Z  |   X  |   C  |   V  |   B  |      |           |      |   N  |   M  |   ,  |   .  |   /  |   ]    |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   | ~L5  | ~L2  | Caps | LAlt | LGui |                                       |  Lft |  Up  |  Dn  | Rght | ~L6  |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        | +L2  | Home |       | PgUp | Del  |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |  End |       | PgDn |      |      |
+     *                                 | BkSp |  ESC |------|       |------| Enter| Space|
+     *                                 |      |      |  Spc |       | Ins  |      |      |
+     *                                 `--------------------'       `--------------------'
+     *
+     *
+     *
+     ****************************************************************************************************
+     *
+     * Under XOrg, I use my own mapping from QWERTY to "Workman for Programmers"
+     * See XOrg files in ./addons/ subdirectory.
+     *
+     * I have to do so, because of two things:
+     * 1) my native language is Russian, and XOrg keymap for it is based on QWERTY layout
+     * 2) I want to have non-standart shifted keys, like $ (as normal) and @ (as shifted), or _ and -
+     *
+     * And even if (2) could be solved using FN* keys (but there is limit in firmware for only 32 such
+     * keys), then (1) can't be solved at firmware level at all.
+     *
+     * So, I have to stick with QWERTY as my main layout + my own XOrg keyboard layout for English.
+     * But sometimes I have to input something when XOrg is not active - for example, in Linux console,
+     * or in firmware console (while debugging firmware), or when keyboard is connected to not my computer.
+     *
+     * For such cases I have Layer1 :)
+     * // hint: switch to Layer1 is only at Layer6
+     *
+     ****************************************************************************************************
+     *
+     *
+     *
+     * Keymap: Default Layer in Workman
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |  ~     |   ;  |   !  |   #  |   {  |   }  |   '  |           |   ^  |   [  |   ]  |   *  |   (  |   )  |   =    |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   Q  |   D  |   R  |   W  |   B  |  NO  |           | ~L7  |   J  |   F  |   U  |   P  |   $  |   :    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | Tab/Shf|   A  |   S  |   H  |   T  |   G  |------|           |------|   Y  |   N  |   E  |   O  |   I  |   -    |
+     * |--------+------+------+------+------+------| Home |           | End  |------+------+------+------+------+--------|
+     * | LCtrl  |   Z  |   X  |   M  |   C  |   V  |      |           |      |   K  |   L  |   ,  |   .  |   /  |   |    |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   | ~L5  | ~L2  | Caps | LAlt | LGui |                                       |  Lft |  Up  |  Dn  | Rght | ~L6  |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |  L0  |  +L2 |       | PgUp | Del  |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |  NO  |       | PgDn |      |      |
+     *                                 | BkSp |  ESC |------|       |------| Enter| Space|
+     *                                 |      |      |  Spc |       | Ins  |      |      |
+     *                                 `--------------------'       `--------------------'
+     *
+     * Keymap: Default Layer in Workman / with Shift
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |  `     |   1  |   2  |   3  |   4  |   5  |   "  |           |   \  |   6  |   7  |   8  |   9  |   0  |   +    |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   Q  |   D  |   R  |   W  |   B  |  NO  |           | ~L7  |   J  |   F  |   U  |   P  |   @  |   %    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | Tab/Shf|   A  |   S  |   H  |   T  |   G  |------|           |------|   Y  |   N  |   E  |   O  |   I  |   _    |
+     * |--------+------+------+------+------+------| Home |           | End  |------+------+------+------+------+--------|
+     * | LCtrl  |   Z  |   X  |   M  |   C  |   V  |      |           |      |   K  |   L  |   ,  |   .  |   /  |   &    |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   | ~L5  | ~L2  | Caps | LAlt | LGui |                                       |  Lft |  Up  |  Dn  | Rght | ~L6  |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |  L0  |  +L2 |       | PgUp | Del  |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |  NO  |       | PgDn |      |      |
+     *                                 | BkSp |  ESC |------|       |------| Enter| Space|
+     *                                 |      |      |  Spc |       | Ins  |      |      |
+     *                                 `--------------------'       `--------------------'
+     *
+     */
+
+    KEYMAP(  // Layer0: default, leftled:none
+        // left hand
+        GRV, 1,   2,   3,   4,   5,   BSLS,
+        FN2, Q,   W,   E,   R,   T,   FN23,
+        FN11,FN28,FN29,FN30,FN31,G,
+        FN12,FN24,FN25,FN26,FN27,B,   HOME,
+        FN21,FN20,CAPS,FN13,FN14,
+                                      FN17,FN19,
+                                           NO,
+                                 FN5, FN6, FN7,
+        // right hand
+             MINS,6,   7,   8,   9,   0,   EQL,
+             FN23,Y,   U,   I,   O,   P,   LBRC,
+                  H,   J,   K,   L,   SCLN,FN15,
+             END, N,   M,   COMM,DOT, SLSH,FN16,
+                       LEFT,UP,  DOWN,RGHT,FN22,
+        PGUP,DEL,
+        PGDN,
+        FN8, FN9, FN10
+    ),
+
+    KEYMAP(  // Layer1: Workman layout, leftled:all
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,Q,   D,   R,   W,   B,   TRNS,
+        TRNS,A,   S,   H,   T,   G,
+        TRNS,Z,   X,   M,   C,   V,   TRNS,
+        TRNS,TRNS,FN17,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,J,   F,   U,   P,   4,   TRNS,
+                  Y,   N,   E,   O,   I,   TRNS,
+             TRNS,K,   L,   TRNS,TRNS,TRNS,TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer2: numpad, leftled:mid/blue
+        // left hand
+        TRNS,NO,  NO,  NO,  NO,  PAUS,PSCR,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  NO,  TRNS,NO,
+        TRNS,NO,  NO,  NO,  TRNS,NO,  TRNS,
+        TRNS,TRNS,FN17,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             SLCK,NLCK,PSLS,PAST,PAST,PMNS,BSPC,
+             TRNS,NO,  P7,  P8,  P9,  PMNS,PGUP,
+                  NO,  P4,  P5,  P6,  PPLS,PGDN,
+             TRNS,NO,  P1,  P2,  P3,  PPLS,PENT,
+                       P0,  PDOT,SLSH,PENT,PENT,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer3: F-keys + PgUp/PgDn on right hand, leftled:bot/green
+        // left hand
+        TRNS,NO,  NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  TRNS,NO,  NO,  NO,
+        TRNS,NO,  TRNS,NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,TRNS,LALT,LGUI,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 LCTL,LSFT,TRNS,
+        // right hand
+             NO,  NO,  NO,  NO,  NO,  NO,  TRNS,
+             TRNS,NO,  F1,  F2,  F3,  F4,  PGUP,
+                  NO,  F5,  F6,  F7,  F8,  PGDN,
+             TRNS,NO,  F9,  F10, F11, F12, APP,
+                       RGUI,RALT,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,RSFT,RCTL
+    ),
+
+    KEYMAP(  // Layer4: unconvenient keys on right hand, leftled:top/white
+        // left hand
+        TRNS,NO,  NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,NO,  NO,  NO,  NO,
+        TRNS,TRNS,NO,  NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,TRNS,LALT,LGUI,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+
+        /* in Workman right hand will be:
+                { } ( ) +
+              ^ ! ?     =
+              ' ! $ " ; \
+              # [ < > ] \
+        */
+
+        // right hand
+             NO,  NO,  4,   5,   9,   0,   PPLS,
+             TRNS,MINS,2,   FN5, 9,   0,   EQL,
+                  BSLS,2,   P,   FN1, 1,   FN2,
+             TRNS,3,   6,   FN3, FN4, 7,   FN2,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer5: F-keys instead of numbers, leftled:top/white
+        // left hand
+        TRNS,F1,  F2,  F3,  F4,  F5,  F6,
+        TRNS,P1,  P2,  P3,  P4,  P5,  TRNS,
+        TRNS,TRNS,TRNS,E,   TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             F7,  F8,  F9,  F10, F11, F12, TRNS,
+             TRNS,P6,  P7,  P8,  P9,  P0,  TRNS,
+                  TRNS,U,   TRNS,TRNS,TRNS,TRNS,
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer6: F-keys + utils(Teensy, Workman-layer switch), leftled:top/white+onboard
+        // left hand
+        FN0, F1,  F2,  F3,  F4,  F5,  F6,
+        TRNS,P1,  P2,  P3,  P4,  P5,  TRNS,
+        TRNS,TRNS,TRNS,E,   TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        FN18,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             F7,  F8,  F9,  F10, F11, F12, FN0,
+             TRNS,P6,  P7,  P8,  P9,  P0,  TRNS,
+                  TRNS,U,   TRNS,TRNS,TRNS,TRNS,
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    //
+    // rarely used
+    //
+
+    KEYMAP(  // Layer7: F-keys only, leftled:top/white
+        // left hand
+        FN0, NO,  NO,  NO,  NO,  NO,  NO,
+        FN1, F13, F14, F15, F16, NO,  TRNS,
+        TRNS,F17, F18, F19, F20, NO,
+        TRNS,F21, F22, F23, F24, NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             NO,  NO,  NO,  NO,  NO,  NO,  TRNS,
+             TRNS,NO,  F1,  F2,  F3,  F4,  TRNS,
+                  NO,  F5,  F6,  F7,  F8,  TRNS,
+             TRNS,NO,  F9,  F10, F11, F12, TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        SLEP,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer8: mouse and navigation, leftled:mid/blue+bot/green
+        // left hand
+        TRNS,NO,  NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  ACL0,NO,  TRNS,
+        TRNS,NO,  NO,  TRNS,ACL1,NO,
+        TRNS,NO,  NO,  TRNS,ACL2,NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+
+        // right hand
+             F16, MPLY,MPRV,MNXT,VOLD,VOLU,MUTE,
+             F14, BTN2,WH_L,WH_U,WH_D,WH_R,PGUP,
+                  BTN1,MS_L,MS_U,MS_D,MS_R,PGDN,
+             F15, BTN3,HOME,END, DEL, INS, NO,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer9: application-specific shortcuts (mostly browser), leftled:top/white+bot/green
+        // left hand
+        TRNS,NO,  NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  TRNS,NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             NO,  NO,  NO,  NO,  NO,  NO,  TRNS,
+             TRNS,NO,  FN12,FN13,FN14,FN15,FN10,
+                  FN1, FN2, FN3, FN4, FN5, FN11,
+             TRNS,TRNS,FN6, FN7, FN8, FN9, FN0,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+/*
+    // templates to copy from
+
+    KEYMAP(  // LayerN: transparent on edges + hard-defined thumb keys, all others are empty
+        // left hand
+        TRNS,NO,  NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,TRNS,LALT,LGUI,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 LCTL,LSFT,TRNS,
+        // right hand
+             NO,  NO,  NO,  NO,  NO,  NO,  TRNS,
+             TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+                  NO,  NO,  NO,  NO,  NO,  TRNS,
+             TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+                       RGUI,RALT,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,RSFT,RCTL
+    ),
+    KEYMAP(  // LayerN: fully transparent
+        // left hand
+        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,
+        // right hand
+             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
+    ),
+*/
+
+};
+
+/* id for user defined functions & macros */
+enum function_id {
+    TEENSY_KEY,
+    CUSTOM_KEY,
+    L_CTRL_ALT_ENT,
+    R_CTRL_ALT_ENT,
+};
+
+enum macro_id {
+    XMONAD_RESET,
+    PASSWORD1,
+    PASSWORD2,
+    PASSWORD3,
+};
+
+/*
+ * Fn action definition
+ */
+const uint16_t PROGMEM fn_actions[] = {
+    [0] =   ACTION_FUNCTION(TEENSY_KEY),                    // FN0  - Teensy key
+
+    [1] =   ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),             // FN1  = Shifted BackSlash // " in Workman
+    [2] =   ACTION_MODS_KEY(MOD_LSFT, KC_MINS),             // FN2  = Shifted Minus     // \ in Workman
+    [3] =   ACTION_MODS_KEY(MOD_LSFT, KC_COMM),             // FN3  = Shifted comma     // < in Workman
+    [4] =   ACTION_MODS_KEY(MOD_LSFT, KC_DOT),              // FN4  = Shifted dot       // > in Workman
+
+    [5] =   ACTION_MODS_TAP_KEY(MOD_LCTL, KC_BSPC),         // FN5  = LShift with tap BackSpace
+    [6] =   ACTION_MODS_TAP_KEY(MOD_LSFT, KC_DEL),          // FN6  = LCtrl  with tap Delete
+    [7] =   ACTION_MODS_TAP_KEY(MOD_LALT, KC_ESC),          // FN7  = LAlt   with tap Escape
+    [8] =   ACTION_MODS_TAP_KEY(MOD_RGUI, KC_INS),          // FN8  = RGui   with tap Ins
+    [9] =   ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT),          // FN9  = RShift with tap Enter
+    [10] =  ACTION_MODS_TAP_KEY(MOD_RCTL, KC_SPC),          // FN10 = RCtrl  with tap Space
+
+    [11] =  ACTION_MODS_TAP_KEY(MOD_LSFT, KC_TAB),          // FN11 = LShift with tap Tab
+    [12] =  ACTION_MODS_TAP_KEY(MOD_LCTL, KC_GRV),          // FN12 = LCtrl  with tap Tilda
+    [13] =  ACTION_MODS_TAP_KEY(MOD_LALT, KC_SPC),          // FN13 = LAlt   with tap Space
+    [14] =  ACTION_MODS_TAP_KEY(MOD_LGUI, KC_ESC),          // FN14 = LGui   with tap Escape
+    [15] =  ACTION_MODS_TAP_KEY(MOD_RSFT, KC_QUOT),         // FN15 = RShift with tap quotes
+    [16] =  ACTION_MODS_TAP_KEY(MOD_RCTL, KC_RBRC),         // FN16 = RCtrl  with tap ]
+
+    [17] =  ACTION_LAYER_SET(0, ON_BOTH),                   // FN17 - set Layer0
+    [18] =  ACTION_LAYER_SET(1, ON_BOTH),                   // FN18 - set Layer1, to use Workman layout at firmware level
+    [19] =  ACTION_LAYER_SET(2, ON_BOTH),                   // FN19 - set Layer2, to use with Numpad keys
+
+    [21] =  ACTION_FUNCTION_TAP(L_CTRL_ALT_ENT),            // FN21 - momentary Layer5+CTRL+ALT on Enter, to use with F* keys on top row
+    [22] =  ACTION_FUNCTION_TAP(R_CTRL_ALT_ENT),            // FN22 - momentary Layer6+CTRL+ALT on Enter, to use with F* keys on top row + utils
+
+    [28] =  ACTION_LAYER_TAP_KEY(4, KC_A),                  // FN28 = momentary Layer4 on A key, to use with unconvenient keys
+    [29] =  ACTION_LAYER_TAP_KEY(3, KC_S),                  // FN29 = momentary Layer3 on S key, to use with F* keys
+    [30] =  ACTION_LAYER_TAP_KEY(8, KC_D),                  // FN30 = momentary Layer8 on D key, to use with mouse and navigation keys
+    [31] =  ACTION_LAYER_TAP_KEY(2, KC_F),                  // FN31 = momentary Layer2 on F key, to use with Numpad keys
+
+    // i'd like to remove this - will try to get used to live without this and convert them to usual keys
+    [20] =  ACTION_LAYER_MOMENTARY(2),                      // FN20 - momentary Layer2, to use with Numpad keys
+// or
+//  [20] =  ACTION_FUNCTION_TAP(CUSTOM_KEY),                // FN20 - use custom key, with tapping support
+
+    [23] =  ACTION_LAYER_TAP_KEY(7, KC_BSLS),               // FN23 - momentary Layer7 on ' , to use with F* keys (F1-F24)
+
+    [24] =  ACTION_LAYER_TAP_KEY(4, KC_Z),                  // FN24 = momentary Layer4 on Z key, to use with unconvenient keys
+    [25] =  ACTION_LAYER_TAP_KEY(3, KC_X),                  // FN25 = momentary Layer3 on X key, to use with F* keys
+    [26] =  ACTION_LAYER_TAP_KEY(8, KC_C),                  // FN26 = momentary Layer8 on C key, to use with mouse and navigation keys
+    [27] =  ACTION_LAYER_TAP_KEY(9, KC_V),                  // FN27 = momentary Layer9 on V key, to use with application-specific shortcuts
+};
+
+const uint16_t PROGMEM fn_actions_4[] = {
+    [1]  =  ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),             // FN1  = Shifted BackSlash // " in Workman
+    [2]  =  ACTION_MODS_KEY(MOD_LSFT, KC_MINS),             // FN2  = Shifted Minus     // \ in Workman
+    [3]  =  ACTION_MODS_KEY(MOD_LSFT, KC_COMM),             // FN3  = Shifted comma     // < in Workman
+    [4]  =  ACTION_MODS_KEY(MOD_LSFT, KC_DOT),              // FN4  = Shifted dot       // > in Workman
+    [5]  =  ACTION_MODS_KEY(MOD_LSFT, KC_SLSH),             // FN5  = Shifted slash     // ? in Workman
+};
+
+const uint16_t PROGMEM fn_actions_7[] = {
+    [0]  =  ACTION_MACRO(XMONAD_RESET),                     // FN0  = xmonad-reanimator
+    [1]  =  ACTION_MACRO(PASSWORD1),                        // FN1  = default password
+    [2]  =  ACTION_MACRO(PASSWORD1),                        // FN2  = other password
+    [3]  =  ACTION_MACRO(PASSWORD1),                        // FN3  = mega password
+};
+
+const uint16_t PROGMEM fn_actions_9[] = {
+    [0]  =  ACTION_MODS_KEY(MOD_LCTL,          KC_P0),      // FN0  = Ctrl+0
+    [1]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P1),      // FN1  = Alt+1
+    [2]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P2),      // FN2  = Alt+2
+    [3]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P3),      // FN3  = Alt+3
+    [4]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P4),      // FN4  = Alt+4
+    [5]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P5),      // FN5  = Alt+5
+    [6]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P6),      // FN6  = Alt+6
+    [7]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P7),      // FN7  = Alt+7
+    [8]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P8),      // FN8  = Alt+8
+    [9]  =  ACTION_MODS_KEY(MOD_LALT,          KC_P9),      // FN9  = Alt+9
+    [10] =  ACTION_MODS_KEY(MOD_LCTL|MOD_LSFT, KC_TAB),     // FN10 = Ctrl+Shift+Tab
+    [11] =  ACTION_MODS_KEY(MOD_LCTL,          KC_TAB),     // FN11 = Ctrl+Tab
+    [12] =  ACTION_MODS_KEY(MOD_LCTL|MOD_LSFT, KC_PGUP),    // FN12 = Ctrl+Shift+PgUp
+    [13] =  ACTION_MODS_KEY(MOD_LCTL|MOD_LSFT, KC_PGDN),    // FN13 = Ctrl+Shift+PgDn
+    [14] =  ACTION_MODS_KEY(MOD_LCTL,          KC_PMNS),    // FN14 = Ctrl+Pad Minus
+    [15] =  ACTION_MODS_KEY(MOD_LCTL,          KC_PPLS),    // FN15 = Ctrl+Pad Plus
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+    // print("action_function called\n");
+    // print("id  = "); phex(id); print("\n");
+    // print("opt = "); phex(opt); print("\n");
+
+    if (id == TEENSY_KEY) {
+        clear_keyboard();
+        print("\n\nJump to bootloader... ");
+        _delay_ms(50);
+        bootloader_jump(); // should not return
+        print("not supported.\n");
+    }
+
+    if (id == L_CTRL_ALT_ENT || id == R_CTRL_ALT_ENT) {
+        if (record->tap.count == 0 || record->tap.interrupted) {
+            uint8_t weak_mods;
+            uint8_t layer;
+
+            if (id == L_CTRL_ALT_ENT) {
+                weak_mods = MOD_BIT(KC_LCTL) | MOD_BIT(KC_LALT);
+                layer     = 5;
+            } else {
+                weak_mods = MOD_BIT(KC_RCTL) | MOD_BIT(KC_RALT);
+                layer     = 6;
+            }
+
+            if (record->event.pressed) {
+                layer_on(layer);
+                add_weak_mods(weak_mods);
+            } else {
+                del_weak_mods(weak_mods);
+                layer_off(layer);
+            }
+        } else {
+            if (record->event.pressed) {
+                add_key(KC_ENT);
+                send_keyboard_report();
+            } else {
+                del_key(KC_ENT);
+                send_keyboard_report();
+            }
+        }
+    }
+
+
+/*
+ * just an example of custom key implementation
+ * not really needed with custom keymap_fn_to_action(),
+ * because it will allow you to have 32 FN** keys on EACH layer
+ */
+
+/*
+    keyevent_t event = record->event;
+
+    if (id == CUSTOM_KEY) {
+        uint8_t layer = biton32(layer_state);
+        uint8_t col = event.key.col;
+        uint8_t row = event.key.row;
+        uint8_t handled = 0;
+
+        if (event.pressed) {
+            if (layer == XXX && col == XXX && row == XXX) {
+                    action_macro_play(
+                        MACRO(
+                            ...........
+                        END)
+                    );
+                    handled++;
+                }
+            }
+        }
+
+        if (!handled) {
+            print("custom key not handled");
+            print(": layer "); pdec(layer);
+            print(", col "); pdec(col);
+            print(", row "); pdec(row);
+            print("\n");
+        }
+    }
+*/
+
+}
+
+#include "keymap_passwords.h"
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
+    if (record->event.pressed) {
+        switch (id) {
+            case XMONAD_RESET:  return MACRO_XMONAD_RESET;
+            case PASSWORD1:     return MACRO_PASSWORD1;
+        }
+    }
+    return MACRO_NONE;
+}
+
+#define FN_ACTIONS_SIZE     (sizeof(fn_actions)   / sizeof(fn_actions[0]))
+#define FN_ACTIONS_4_SIZE   (sizeof(fn_actions_4) / sizeof(fn_actions_4[0]))
+#define FN_ACTIONS_7_SIZE   (sizeof(fn_actions_7) / sizeof(fn_actions_7[0]))
+#define FN_ACTIONS_9_SIZE   (sizeof(fn_actions_9) / sizeof(fn_actions_9[0]))
+
+/*
+ * translates Fn keycode to action
+ * for some layers, use different translation table
+ */
+action_t keymap_fn_to_action(uint8_t keycode)
+{
+    uint8_t layer = biton32(layer_state);
+
+    action_t action;
+    action.code = ACTION_NO;
+
+    if (layer == 4 && FN_INDEX(keycode) < FN_ACTIONS_4_SIZE) {
+        action.code = pgm_read_word(&fn_actions_4[FN_INDEX(keycode)]);
+    }
+
+    if (layer == 7 && FN_INDEX(keycode) < FN_ACTIONS_7_SIZE) {
+        action.code = pgm_read_word(&fn_actions_7[FN_INDEX(keycode)]);
+    }
+
+    if (layer == 9 && FN_INDEX(keycode) < FN_ACTIONS_9_SIZE) {
+        action.code = pgm_read_word(&fn_actions_9[FN_INDEX(keycode)]);
+    }
+
+    // by default, use fn_actions from default layer 0
+    // this is needed to get mapping for same key, that was used switch to some layer,
+    // to have possibility to switch layers back
+    if (action.code == ACTION_NO && FN_INDEX(keycode) < FN_ACTIONS_SIZE) {
+        action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
+    }
+
+    return action;
+}
+
diff --git a/keyboard/ergodox/keymap_dvorak.c b/keyboard/ergodox/keymap_dvorak.c
new file mode 100755 (executable)
index 0000000..a499518
--- /dev/null
@@ -0,0 +1,232 @@
+#include "bootloader.h"
+#include "keymap_common.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+    /*
+     * Keymap: Default Layer in Dvorak (Layer 0)
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |   +    |   1  |   2  |   3  |   4  |   5  |  Esc |           |  ESC |   6  |   7  |   8  |   9  |   0  |   -    |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   '  |   ,  |   .  |   Y  |   Y  |(Null)|           |(Null)|   F  |   G  |   C  |   R  |   L  |   /    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | CapsLk |   A  |   O  |   E  |   U  |   I  |------|           |------|   D  |   H  |   T  |   N  |   S  |   \    |
+     * |--------+------+------+------+------+------| FN1  |           | FN2  |------+------+------+------+------+--------|
+     * | LShift |   Z  |   X  |   C  |   V  |   X  |      |           |      |   B  |   M  |   W  |   V  |   Z  | RShift |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   | LGUI |   `  |  INS | Left | Rght |                                       |  Up  |  Dn  |   [  |   ]  | RGUI |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        | LCtr | LAlt |       | Ralt | RCtr |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      | Home |       | PgUp |      |      |
+     *                                 | BkSp | Del  |------|       |------| Enter| Space|
+     *                                 |      |      | End  |       | PgDn |      |      |
+     *                                 `--------------------'       `--------------------'
+     *
+     *
+     *****************************************************************************************************
+     * This Dvorak keyboard layout stems from my early Kinesis years, using the Contour PS/2 with a Dvorak
+     * software layout. Because of this, the RBRC and LBRC were on opposite sides of the board in the cor-
+     * ner keys. I've decided to continue using this layout with my ErgoDox.
+     */
+
+    KEYMAP(  // layer 0 : default
+        // left hand
+        EQL,    1,    2,   3,   4,   5,   ESC,
+        TAB, QUOT, COMM, DOT,   P,   Y,    NO,
+        CAPS,   A,    O,   E,   U,   I,
+        LSFT, SCLN,   Q,   J,   K,   X,   FN1,
+        LGUI,  GRV, INS,LEFT,RGHT,
+                                      LCTL,LALT,
+                                           HOME,
+                                 BSPC,DEL, END,
+        // right hand
+             ESC,  6,   7,   8,   9,   0,  MINS,
+             NO,   F,   G,   C,   R,   L,  SLSH,
+                   D,   H,   T,   N,   S,  BSLS,
+             FN2,  B,   M,   W,   V,   Z,  RSFT,
+                        UP,DOWN,RBRC,LBRC,  RGUI,
+        RALT,RCTL,
+        PGUP,
+        PGDN,ENT, SPC
+    ),
+
+
+    /* 
+     * Keymap: Function and Media Keys Layer (Layer 1)
+     * 
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * | TEENSY |  F1  |  F2  |  F3  |  F4  |  F5  | F11  |           |  F12 |  F6  |  F7  |  F8  |  F9  |  F10 |  Mute  |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * |        |      |      |      |      |      | FN4  |           |  FN6 |      | PrSc | ScLk | Paus |      | Vol Up |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * |        |      |      |      |      |      |------|           |------| Stop | Prev | Play | Next | Sel  | Vol Dn |
+     * |--------+------+------+------+------+------| FN4  |           |  FN7 |------+------+------+------+------+--------|
+     * |        |      |      |      |      |      |      |           |      |      |      |      |      |      |        |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   |      |      |      |      |      |                                       |      |      |      |      |      |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |      |      |       |      |      |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |      |       |      |      |      |
+     *                                 |      |      |------|       |------|      |      |
+     *                                 |      |      |      |       |      |      |      |
+     *                                 `--------------------'       `--------------------'
+     * 
+     * 
+     */
+
+    KEYMAP(  // layer 1 : function and media keys
+        // left hand
+        FN0, F1,  F2,  F3,  F4,  F5,  F11,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN4,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN4,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             F12, F6,  F7,  F8,  F9,  F10, MUTE,
+             FN6, TRNS,PSCR,SLCK,PAUS,TRNS,VOLU,
+                  MSTP,MPRV,MPLY,MNXT,MSEL,VOLD,
+             FN7, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+
+    /* 
+     * Keymap: Numpad Layer (Layer 2)
+     * 
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * | Power  |      |      |      |      |      |      |           |      |      | NmLk | KP / | KP * | KP - |        |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Sleep  |      |      |      |      |      | FN5  |           |  FN4 |      | KP 7 | KP 8 | KP 9 | KP + |        |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | Wake   |      |      |      |      |      |------|           |------|      | KP 4 | KP 5 | KP 6 | KP + |        |
+     * |--------+------+------+------+------+------| FN7  |           |  FN4 |------+------+------+------+------+--------|
+     * |        |      |      |      |      |      |      |           |      |      | KP 1 | KP 2 | KP 3 |KP Ent|        |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   |      |      |      |      |      |                                       | KP 0 |      | KP . |KP Ent|      |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |      |      |       |      |      |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |      |       |      |      |      |
+     *                                 |      |      |------|       |------|      |      |
+     *                                 |      |      |      |       |      |      |      |
+     *                                 `--------------------'       `--------------------'
+     * 
+     */
+
+    KEYMAP(  // layer 2: numpad
+        // left hand
+        PWR, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        SLEP,TRNS,TRNS,TRNS,TRNS,TRNS, FN5,
+        WAKE,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, FN7,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             TRNS,TRNS,NLCK,PSLS,PAST,PMNS,TRNS,
+              FN4,NO,  P7,  P8,  P9,  PPLS,TRNS,
+                  NO,  P4,  P5,  P6,  PPLS,TRNS,
+              FN4,NO,  P1,  P2,  P3,  PENT,TRNS,
+                       P0,  TRNS,PDOT,PENT,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+
+    /* 
+     * Keymap: QWERTY Gaming Layer (Layer 3)
+     * 
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |   =    |   1  |   2  |   3  |   4  |   5  | ESC  |           | ESC  |   6  |   7  |   8  |   9  |   0  |   -    |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   Q  |   W  |   E  |   R  |   T  | Fn4  |           | Fn4  |   Y  |   U  |   I  |   O  |   P  |   [    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | CapsLk |   A  |   S  |   D  |   F  |   G  |------|           |------|   H  |   J  |   K  |   L  |   ;  |   '    |
+     * |--------+------+------+------+------+------| Fn1  |           | Fn2  |------+------+------+------+------+--------|
+     * | LShift |   Z  |   X  |   C  |   V  |   B  |      |           |      |   N  |   M  |   ,  |   .  |   /  | RShift |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   | LGUI |   `  |  INS | Left | Rght |                                       |  Up  |  Dn  |   [  |   ]  | RGUI |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        | LCtr | LAlt |       | Ralt | RCtr |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      | Home |       | PgUp |      |      |
+     *                                 | BkSp | Del  |------|       |------| Enter| Space|
+     *                                 |      |      | End  |       | PgDn |      |      |
+     *                                 `--------------------'       `--------------------'
+     * 
+     */
+
+    KEYMAP(  // layer 3 : QWERTY Gaming
+        // left hand
+        EQL, 1,   2,   3,   4,   5,   ESC,
+        TAB, Q,   W,   E,   R,   T,   FN4,
+        CAPS,A,   S,   D,   F,   G,
+        LSFT,Z,   X,   C,   V,   B,   FN1,
+        LGUI,GRV, INS,LEFT,RGHT,
+                                      LCTL,LALT,
+                                           HOME,
+                                 BSPC,DEL, END,
+        // right hand
+             ESC, 6,   7,   8,   9,   0,   MINS,
+             FN4, Y,   U,   I,   O,   P,   BSLS,
+                  H,   J,   K,   L,   SCLN,QUOT,
+             FN2, N,   M,   COMM,DOT, SLSH,RSFT,
+                       UP,DOWN,LBRC,RBRC,RGUI,
+        RALT,RCTL,
+        PGUP,
+        PGDN,ENT, SPC
+    ),
+
+};
+
+/* id for user defined functions & macros */
+enum function_id {
+    TEENSY_KEY,
+};
+
+/*
+ * Fn action definition
+ */
+const uint16_t PROGMEM fn_actions[] = {
+    ACTION_FUNCTION(TEENSY_KEY),                    // FN0 - Teensy key
+    ACTION_LAYER_MOMENTARY(1),                      // FN1 - switch to Layer1
+    ACTION_LAYER_MOMENTARY(2),                      // FN2 - switch to Layer2
+    ACTION_LAYER_MOMENTARY(3),                      // FN3 - switch to Layer3
+    ACTION_LAYER_SET_CLEAR(0),                      // FN4 - set Layer0
+    ACTION_LAYER_SET(1, ON_PRESS),                  // FN5 - set Layer1
+    ACTION_LAYER_SET(2, ON_PRESS),                  // FN6 - set Layer2
+    ACTION_LAYER_SET(3, ON_PRESS),                  // FN7 - set Layer3
+};
+
+/*
+ * Defining the Teensy Key action_function
+ */
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+    // print("action_function called\n");
+    // print("id  = "); phex(id); print("\n");
+    // print("opt = "); phex(opt); print("\n");
+
+    if (id == TEENSY_KEY) {
+        clear_keyboard();
+        print("\n\nJump to bootloader... ");
+        _delay_ms(50);
+        bootloader_jump(); // should not return
+        print("not supported.\n");
+    }
+
+}
diff --git a/keyboard/ergodox/keymap_micro.c b/keyboard/ergodox/keymap_micro.c
new file mode 100755 (executable)
index 0000000..8090678
--- /dev/null
@@ -0,0 +1,428 @@
+//
+// Inspired by MicroDox:
+// http://geekhack.org/index.php?topic=42231.msg1062851#msg1062851
+// https://www.massdrop.com/ext/ergodox/?referer=CTL63V&hash=9ff8ddbb75e03e517aaa39acabc81669
+//
+#include <util/delay.h>
+#include "bootloader.h"
+#include "keymap_common.h"
+
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+    /*
+     * Keymap: Default Layer in QWERTY
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |        |      |      |      |      |      |      |           |      |      |      |      |      |      |        |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   Q  |   W  |   E  |   R  |   T  |      |           |      |   Y  |   U  |   I  |   O  |   P  |   [    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | Tab/Shf|   A  |   S  |   D  |   F  |   G  |------|           |------|   H  |   J  |   K  |   L  |   ;  |   '    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | LCtrl/~|   Z  |   X  |   C  |   V  |   B  |      |           |      |   N  |   M  |   ,  |   .  |   /  |   ]    |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   |      |      | Caps | LAlt | LGui |                                       | RGui |      |      |      |      |
+     *   |      |      |      | Spc  | Esc  |                                       |      |      |      |      |      |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |      |      |       |      |      |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |      |       |      |      |      |
+     *                                 | BkSp |  Del |------|       |------| Enter| Space|
+     *                                 |      |      |  Esc |       | Ins  |      |      |
+     *                                 | LCtl | LSft | LAlt |       | RAlt | RSft | RCtl |
+     *                                 `--------------------'       `--------------------'
+     *
+     *
+     *
+     ****************************************************************************************************
+     *
+     * Under XOrg, I use my own mapping from QWERTY to "Workman for Programmers"
+     * See XOrg files in ./addons/ subdirectory.
+     *
+     * I have to do so, because of two things:
+     * 1) my native language is Russian, and XOrg keymap for it is based on QWERTY layout
+     * 2) I want to have non-standart shifted keys, like $ (as normal) and @ (as shifted), or _ and -
+     *
+     * And even if (2) could be solved using FN* keys (but there is limit in firmware for only 32 such
+     * keys), then (1) can't be solved at firmware level at all.
+     *
+     * So, I have to stick with QWERTY as my main layout + my own XOrg keyboard layout for English.
+     * But sometimes I have to input something when XOrg is not active - for example, in Linux console,
+     * or in firmware console (while debugging firmware), or when keyboard is connected to not my computer.
+     *
+     * For such cases I have Layer1 :)
+     * // hint: switch to Layer1 is only at Layer6
+     *
+     ****************************************************************************************************
+     *
+     *
+     *
+     * Keymap: Default Layer in Workman
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |        |      |      |      |      |      |      |           |      |      |      |      |      |      |        |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   Q  |   D  |   R  |   W  |   B  |      |           |      |   J  |   F  |   U  |   P  |   $  |   :    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | Tab/Shf|   A  |   S  |   H  |   T  |   G  |------|           |------|   Y  |   N  |   E  |   O  |   I  |   -    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | LCtrl  |   Z  |   X  |   M  |   C  |   V  |      |           |      |   K  |   L  |   ,  |   .  |   /  |   |    |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   |      |      | Caps | LAlt | LGui |                                       | RGui |      |      |      |      |
+     *   |      |      |      | Spc  | Esc  |                                       |      |      |      |      |      |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |      |      |       |      |      |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |      |       |      |      |      |
+     *                                 | BkSp |  Del |------|       |------| Enter| Space|
+     *                                 |      |      |  Esc |       | Ins  |      |      |
+     *                                 | LCtl | LSft | LAlt |       | RAlt | RSft | RCtl |
+     *                                 `--------------------'       `--------------------'
+     *
+     * Keymap: Default Layer in Workman / with Shift
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |        |      |      |      |      |      |      |           |      |      |      |      |      |      |        |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   Q  |   D  |   R  |   W  |   B  |      |           |      |   J  |   F  |   U  |   P  |   @  |   %    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | Tab/Shf|   A  |   S  |   H  |   T  |   G  |------|           |------|   Y  |   N  |   E  |   O  |   I  |   _    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | LCtrl  |   Z  |   X  |   M  |   C  |   V  |      |           |      |   K  |   L  |   ,  |   .  |   /  |   &    |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   |      |      | Caps | LAlt | LGui |                                       | RGui |      |      |      |      |
+     *   |      |      |      | Spc  | Esc  |                                       |      |      |      |      |      |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        |      |      |       |      |      |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |      |       |      |      |      |
+     *                                 | BkSp |  Del |------|       |------| Enter| Space|
+     *                                 |      |      |  Esc |       | Ins  |      |      |
+     *                                 | LCtl | LSft | LAlt |       | RAlt | RSft | RCtl |
+     *                                 `--------------------'       `--------------------'
+     *
+     * |  ~     |   ;  |   !  |   #  |   {  |   }  |   '  |           |   ^  |   [  |   ]  |   *  |   (  |   )  |   =    |
+     * |  `     |   1  |   2  |   3  |   4  |   5  |   "  |           |   \  |   6  |   7  |   8  |   9  |   0  |   +    |
+     */
+
+    KEYMAP(  // Layer0: default, leftled:none
+        // left hand
+        NO,  NO,  NO,  NO,  NO,  NO,  NO,
+        TAB, Q,   W,   E,   R,   T,   NO,
+        FN11,FN28,FN29,FN30,FN21,G,
+        FN12,FN24,FN25,FN26,FN27,B,   NO,
+        NO,  NO,  CAPS,FN13,FN14,
+                                      NO,  NO,
+                                           NO,
+                                 FN5, FN6, FN7,
+        // right hand
+             NO,  NO,  NO,  NO,  NO,  NO,  NO,
+             NO,  Y,   U,   I,   O,   P,   LBRC,
+                  H,   J,   K,   L,   FN22,FN15,
+             NO,  N,   M,   COMM,DOT, SLSH,FN16,
+                       RGUI,FN17,NO,  NO,  NO,
+        NO,  NO,
+        NO,
+        FN8, FN9, FN10
+    ),
+
+    KEYMAP(  // Layer1: Workman layout, leftled:all
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,Q,   D,   R,   W,   B,   TRNS,
+        TRNS,A,   S,   H,   T,   G,
+        TRNS,Z,   X,   M,   C,   V,   TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,J,   F,   U,   P,   4,   TRNS,
+                  Y,   N,   E,   O,   I,   TRNS,
+             TRNS,K,   L,   TRNS,TRNS,TRNS,TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer2: numpad, leftled:blue
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  NO,  TRNS,NO,
+        TRNS,NO,  NO,  NO,  TRNS,NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,NLCK,P7,  P8,  P9,  PMNS,PGUP,
+                  PAST,P4,  P5,  P6,  PPLS,PGDN,
+             TRNS,FN17,P1,  P2,  P3,  PSLS,PENT,
+                       P0,  PDOT,SLSH,NO,  NO,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer3: F-keys + PgUp/PgDn on right hand, leftled:green
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  TRNS,NO,  NO,  NO,
+        TRNS,NO,  TRNS,NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,TRNS,LALT,LGUI,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 LCTL,LSFT,LALT,
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,PSCR,F1,  F2,  F3,  F4,  PGUP,
+                  SLCK,F5,  F6,  F7,  F8,  PGDN,
+             TRNS,PAUS,F9,  F10, F11, F12, APP,
+                       RGUI,RALT,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        RALT,RSFT,RCTL
+    ),
+
+    KEYMAP(  // Layer4: unconvenient keys on right hand, leftled:red
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,NO,  NO,  NO,  NO,
+        TRNS,TRNS,NO,  NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+
+        /* in Workman right hand will be:
+         *
+         *    ^ { } ( ) +
+         *    ' ! $ " ; =
+         *    # [ < > ] \
+         */
+
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,MINS,4,   5,   9,   0,   PPLS,
+                  BSLS,2,   P,   FN1, 1,   EQL,
+             TRNS,3,   6,   FN3, FN4, 7,   FN2,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer5: cursor, leftled:red
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  NO,  TRNS,NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,PGUP,HOME,END, DEL, INS, PGUP,
+                  PGDN,LEFT,UP,  DOWN,RGHT,PGDN,
+             TRNS,NO,  HOME,END, DEL, INS, TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer6: F1-F10, Workman-layer switch, Teensy, layer switches, leftled:red+onboard
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        FN0, F1,  F2,  F3,  F4,  F5,  TRNS,
+        TRNS,FN18,NO,  NO,  FN19,NO,
+        TRNS,NO,  NO,  NO,  FN19,NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,F6,  F7,  F8,  F9,  F10, FN0,
+                  FN0, NO,  NO,  NO,  TRNS,TRNS,
+             TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    //
+    // rarely used
+    //
+
+    KEYMAP(  // Layer7: F-keys only, leftled:red
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,F13, F14, F15, F16, NO,  TRNS,
+        TRNS,F17, F18, F19, F20, NO,
+        TRNS,F21, F22, F23, F24, NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,NO,  F1,  F2,  F3,  F4,  TRNS,
+                  NO,  F5,  F6,  F7,  F8,  TRNS,
+             TRNS,NO,  F9,  F10, F11, F12, TRNS,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+    KEYMAP(  // Layer8: mouse and navigation, leftled:blue and green
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  TRNS,NO,  NO,
+        TRNS,NO,  NO,  TRNS,NO,  NO,  TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,BTN2,WH_L,WH_U,WH_D,WH_R,PGUP,
+                  BTN1,MS_L,MS_U,MS_D,MS_R,PGDN,
+             TRNS,BTN3,HOME,END, DEL, INS, NO,
+                       TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,TRNS,TRNS
+    ),
+
+/*
+    // templates to copy from
+
+    KEYMAP(  // LayerN: transparent on edges + hard-defined thumb keys, all others are empty
+        // left hand
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,NO,  NO,  NO,  NO,  NO,
+        TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+        TRNS,TRNS,TRNS,LALT,LGUI,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 LCTL,LSFT,TRNS,
+        // right hand
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+                  NO,  NO,  NO,  NO,  NO,  TRNS,
+             TRNS,NO,  NO,  NO,  NO,  NO,  TRNS,
+                       RGUI,RALT,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,RSFT,RCTL
+    ),
+    KEYMAP(  // LayerN: fully transparent
+        // left hand
+        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,
+        // right hand
+             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
+    ),
+*/
+
+};
+
+/* id for user defined functions */
+enum function_id {
+    TEENSY_KEY,
+};
+
+/*
+ * Fn action definition
+ */
+const uint16_t PROGMEM fn_actions[] = {
+    ACTION_FUNCTION(TEENSY_KEY),                    // FN0  - Teensy key
+
+    // Layer4: unconvenient keys on right hand
+    ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),             // FN1  = Shifted BackSlash // " in Workman
+    ACTION_MODS_KEY(MOD_LSFT, KC_MINS),             // FN2  = Shifted Minus     // \ in Workman
+    ACTION_MODS_KEY(MOD_LSFT, KC_COMM),             // FN3  = Shifted comma     // < in Workman
+    ACTION_MODS_KEY(MOD_LSFT, KC_DOT),              // FN4  = Shifted dot       // > in Workman
+
+    // Dual-role keys on thumbs
+    ACTION_MODS_TAP_KEY(MOD_LCTL, KC_BSPC),         // FN5  = LShift with tap BackSpace
+    ACTION_MODS_TAP_KEY(MOD_LSFT, KC_DEL),          // FN6  = LCtrl  with tap Delete
+    ACTION_MODS_TAP_KEY(MOD_LALT, KC_ESC),          // FN7  = LAlt   with tap Escape
+    ACTION_MODS_TAP_KEY(MOD_RALT, KC_INS),          // FN8  = RAlt   with tap Ins
+    ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT),          // FN9  = RShift with tap Enter
+    ACTION_MODS_TAP_KEY(MOD_RCTL, KC_SPC),          // FN10 = RCtrl  with tap Space
+
+    // Dual-role keys on pinkies
+    ACTION_MODS_TAP_KEY(MOD_LSFT, KC_TAB),          // FN11 = LShift with tap Tab
+    ACTION_MODS_TAP_KEY(MOD_LCTL, KC_GRV),          // FN12 = LCtrl  with tap Tilda
+    ACTION_MODS_TAP_KEY(MOD_LALT, KC_SPC),          // FN13 = LAlt   with tap Space
+    ACTION_MODS_TAP_KEY(MOD_LGUI, KC_ESC),          // FN14 = LGui   with tap Escape
+    ACTION_MODS_TAP_KEY(MOD_RSFT, KC_QUOT),         // FN15 = RShift with tap quotes
+    ACTION_MODS_TAP_KEY(MOD_RCTL, KC_RBRC),         // FN16 = RCtrl  with tap ]
+
+    // Layers switching
+    ACTION_LAYER_SET(0, ON_BOTH),                   // FN17 - set Layer0
+    ACTION_LAYER_SET(1, ON_BOTH),                   // FN18 - set Layer1, to use Workman layout at firmware level
+    ACTION_LAYER_SET(2, ON_BOTH),                   // FN19 - set Layer2, to use with Numpad keys
+
+    ACTION_LAYER_MOMENTARY(2),                      // UNUSED: FN20 - momentary Layer2, to use with Numpad keys
+    ACTION_LAYER_TAP_KEY(5, KC_F),                  // FN21 - momentary Layer5, to use with cursor
+    ACTION_LAYER_TAP_KEY(6, KC_SCLN),               // FN22 - tapping ; Layer6, to use with F1-F10, Workman-layer switch, Teensy, layer switches
+    ACTION_LAYER_MOMENTARY(7),                      // UNUSED: FN23 - momentary Layer7, to use with F* keys (F1-F24)
+
+    ACTION_LAYER_TAP_KEY(4, KC_Z),                  // FN24 = momentary Layer4 on Z key, to use with unconvenient keys
+    ACTION_LAYER_TAP_KEY(3, KC_X),                  // FN25 = momentary Layer3 on X key, to use with F* keys
+    ACTION_LAYER_TAP_KEY(8, KC_C),                  // FN26 = momentary Layer8 on C key, to use with mouse and navigation keys
+    ACTION_LAYER_TAP_KEY(2, KC_V),                  // FN27 = momentary Layer2 on V key, to use with Numpad keys
+
+    // i'd like to remove this - will try to get used to live without this and convert them to usual keys
+    ACTION_LAYER_TAP_KEY(4, KC_A),                  // FN28 = momentary Layer4 on A key, to use with unconvenient keys
+    ACTION_LAYER_TAP_KEY(3, KC_S),                  // FN29 = momentary Layer3 on S key, to use with F* keys
+    ACTION_LAYER_TAP_KEY(8, KC_D),                  // FN30 = momentary Layer8 on D key, to use with mouse and navigation keys
+    ACTION_LAYER_TAP_KEY(2, KC_F),                  // UNUSED: FN31 = momentary Layer2 on F key, to use with Numpad keys
+};
+
+void action_function(keyrecord_t *event, uint8_t id, uint8_t opt)
+{
+    print("action_function called\n");
+    print("id  = "); phex(id); print("\n");
+    print("opt = "); phex(opt); print("\n");
+    if (id == TEENSY_KEY) {
+        clear_keyboard();
+        print("\n\nJump to bootloader... ");
+        _delay_ms(250);
+        bootloader_jump(); // should not return
+        print("not supported.\n");
+    }
+}
+
diff --git a/keyboard/ergodox/keymap_passwords_example.h b/keyboard/ergodox/keymap_passwords_example.h
new file mode 100755 (executable)
index 0000000..01398d9
--- /dev/null
@@ -0,0 +1,21 @@
+#define MACRO_XMONAD_RESET  MACRO( \
+                                I(15), \
+                                D(LCTL), D(LALT), T(F2), W(255), U(LALT), U(LCTL), W(255), \
+                                T(X), T(M), T(O), T(N), T(UP), T(ENT), W(255), \
+                                D(LCTL), D(LALT), T(F5), W(255), U(LALT), U(LCTL), W(255), \
+                            END) \
+
+#define MACRO_PASSWORD1     MACRO( \
+                                I(15), \
+                                T(E), T(X), T(A), T(M), T(P), T(L), T(E), \
+                            END) \
+
+#define MACRO_PASSWORD2     MACRO( \
+                                I(15), \
+                                T(E), T(X), T(A), T(M), T(P), T(L), T(E), \
+                            END) \
+
+#define MACRO_PASSWORD2     MACRO( \
+                                I(15), \
+                                T(E), T(X), T(A), T(M), T(P), T(L), T(E), \
+                            END) \
diff --git a/keyboard/ergodox/led.c b/keyboard/ergodox/led.c
new file mode 100755 (executable)
index 0000000..765386e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+Copyright 2013 Oleg Kostyuk <cub.uanic@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 <stdint.h>
+#include <avr/io.h>
+#include "print.h"
+#include "debug.h"
+#include "led.h"
+#include "ergodox.h"
+
+
+void led_set(uint8_t usb_led)
+{
+    // topmost - NumLock
+#ifndef INVERT_NUMLOCK
+    if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+        ergodox_right_led_1_on();
+    } else {
+        ergodox_right_led_1_off();
+    }
+#else
+    if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+        ergodox_right_led_1_off();
+    } else {
+        ergodox_right_led_1_on();
+    }
+#endif
+
+    // middle - CapsLock
+    if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+        ergodox_right_led_2_on();
+    } else {
+        ergodox_right_led_2_off();
+    }
+
+    // bottommost - ScrollLock
+    if (usb_led & (1<<USB_LED_SCROLL_LOCK)) {
+        ergodox_right_led_3_on();
+    } else {
+        ergodox_right_led_3_off();
+    }
+}
diff --git a/keyboard/ergodox/matrix.c b/keyboard/ergodox/matrix.c
new file mode 100755 (executable)
index 0000000..cecfe57
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+Copyright 2013 Oleg Kostyuk <cub.uanic@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 <avr/io.h>
+#include <util/delay.h>
+#include "action_layer.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "ergodox.h"
+#include "i2cmaster.h"
+#ifdef DEBUG_MATRIX_SCAN_RATE
+#include  "timer.h"
+#endif
+
+#ifndef DEBOUNCE
+#   define DEBOUNCE    5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(uint8_t row);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+static uint8_t mcp23018_reset_loop;
+
+#ifdef DEBUG_MATRIX_SCAN_RATE
+uint32_t matrix_timer;
+uint32_t matrix_scan_count;
+#endif
+
+inline
+uint8_t matrix_rows(void)
+{
+    return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+    return MATRIX_COLS;
+}
+
+void matrix_init(void)
+{
+    // initialize row and col
+    init_ergodox();
+    mcp23018_status = init_mcp23018();
+    ergodox_blink_all_leds();
+    unselect_rows();
+    init_cols();
+
+    // initialize matrix state: all keys off
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+        matrix[i] = 0;
+        matrix_debouncing[i] = 0;
+    }
+
+#ifdef DEBUG_MATRIX_SCAN_RATE
+    matrix_timer = timer_read32();
+    matrix_scan_count = 0;
+#endif
+}
+
+uint8_t matrix_scan(void)
+{
+    if (mcp23018_status) { // if there was an error
+        if (++mcp23018_reset_loop == 0) {
+            // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
+            // this will be approx bit more frequent than once per second
+            print("trying to reset mcp23018\n");
+            mcp23018_status = init_mcp23018();
+            if (mcp23018_status) {
+                print("left side not responding\n");
+            } else {
+                print("left side attached\n");
+                ergodox_blink_all_leds();
+            }
+        }
+    }
+
+#ifdef DEBUG_MATRIX_SCAN_RATE
+    matrix_scan_count++;
+
+    uint32_t timer_now = timer_read32();
+    if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
+        print("matrix scan frequency: ");
+        pdec(matrix_scan_count);
+        print("\n");
+
+        matrix_timer = timer_now;
+        matrix_scan_count = 0;
+    }
+#endif
+
+#ifdef KEYMAP_CUB
+    uint8_t layer = biton32(layer_state);
+
+    ergodox_board_led_off();
+    ergodox_left_led_1_off();
+    ergodox_left_led_2_off();
+    ergodox_left_led_3_off();
+    switch (layer) {
+        case 1:
+            // all
+            ergodox_left_led_1_on();
+            ergodox_left_led_2_on();
+            ergodox_left_led_3_on();
+            break;
+        case 2:
+            // blue
+            ergodox_left_led_2_on();
+            break;
+        case 8:
+            // blue and green
+            ergodox_left_led_2_on();
+            // break missed intentionally
+        case 3:
+            // green
+            ergodox_left_led_3_on();
+            break;
+        case 6:
+            ergodox_board_led_on();
+            // break missed intentionally
+        case 4:
+        case 5:
+        case 7:
+            // white
+            ergodox_left_led_1_on();
+            break;
+        case 9:
+            // white+green
+            ergodox_left_led_1_on();
+            ergodox_left_led_3_on();
+            break;
+        default:
+            // none
+            break;
+    }
+
+    mcp23018_status = ergodox_left_leds_update();
+#endif
+
+    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+        select_row(i);
+        matrix_row_t cols = read_cols(i);
+        if (matrix_debouncing[i] != cols) {
+            matrix_debouncing[i] = cols;
+            if (debouncing) {
+                debug("bounce!: "); debug_hex(debouncing); debug("\n");
+            }
+            debouncing = DEBOUNCE;
+        }
+        unselect_rows();
+    }
+
+    if (debouncing) {
+        if (--debouncing) {
+            _delay_ms(1);
+        } else {
+            for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+                matrix[i] = matrix_debouncing[i];
+            }
+        }
+    }
+
+    return 1;
+}
+
+bool matrix_is_modified(void)
+{
+    if (debouncing) return false;
+    return true;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+    return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+    return matrix[row];
+}
+
+void matrix_print(void)
+{
+    print("\nr/c 0123456789ABCDEF\n");
+    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+        phex(row); print(": ");
+        pbin_reverse16(matrix_get_row(row));
+        print("\n");
+    }
+}
+
+uint8_t matrix_key_count(void)
+{
+    uint8_t count = 0;
+    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+        count += bitpop16(matrix[i]);
+    }
+    return count;
+}
+
+/* Column pin configuration
+ *
+ * Teensy
+ * col: 0   1   2   3   4   5
+ * pin: F0  F1  F4  F5  F6  F7
+ *
+ * MCP23018
+ * col: 0   1   2   3   4   5
+ * pin: B5  B4  B3  B2  B1  B0
+ */
+static void  init_cols(void)
+{
+    // init on mcp23018
+    // not needed, already done as part of init_mcp23018()
+
+    // init on teensy
+    // Input with pull-up(DDR:0, PORT:1)
+    DDRF  &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
+    PORTF |=  (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
+}
+
+static matrix_row_t read_cols(uint8_t row)
+{
+    if (row < 7) {
+        if (mcp23018_status) { // if there was an error
+            return 0;
+        } else {
+            uint8_t data = 0;
+            mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out;
+            mcp23018_status = i2c_write(GPIOB);             if (mcp23018_status) goto out;
+            mcp23018_status = i2c_start(I2C_ADDR_READ);     if (mcp23018_status) goto out;
+            data = i2c_readNak();
+            data = ~data;
+        out:
+            i2c_stop();
+            return data;
+        }
+    } else {
+        _delay_us(30);  // without this wait read unstable value.
+        // read from teensy
+        return
+            (PINF&(1<<0) ? 0 : (1<<0)) |
+            (PINF&(1<<1) ? 0 : (1<<1)) |
+            (PINF&(1<<4) ? 0 : (1<<2)) |
+            (PINF&(1<<5) ? 0 : (1<<3)) |
+            (PINF&(1<<6) ? 0 : (1<<4)) |
+            (PINF&(1<<7) ? 0 : (1<<5)) ;
+    }
+}
+
+/* Row pin configuration
+ *
+ * Teensy
+ * row: 7   8   9   10  11  12  13
+ * pin: B0  B1  B2  B3  D2  D3  C6
+ *
+ * MCP23018
+ * row: 0   1   2   3   4   5   6
+ * pin: A0  A1  A2  A3  A4  A5  A6
+ */
+static void unselect_rows(void)
+{
+    // unselect on mcp23018
+    if (mcp23018_status) { // if there was an error
+        // do nothing
+    } else {
+        // set all rows hi-Z : 1
+        mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out;
+        mcp23018_status = i2c_write(GPIOA);             if (mcp23018_status) goto out;
+        mcp23018_status = i2c_write( 0xFF
+                              & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
+                          );                            if (mcp23018_status) goto out;
+    out:
+        i2c_stop();
+    }
+
+    // unselect on teensy
+    // Hi-Z(DDR:0, PORT:0) to unselect
+    DDRB  &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
+    PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
+    DDRD  &= ~(1<<2 | 1<<3);
+    PORTD &= ~(1<<2 | 1<<3);
+    DDRC  &= ~(1<<6);
+    PORTC &= ~(1<<6);
+}
+
+static void select_row(uint8_t row)
+{
+    if (row < 7) {
+        // select on mcp23018
+        if (mcp23018_status) { // if there was an error
+            // do nothing
+        } else {
+            // set active row low  : 0
+            // set other rows hi-Z : 1
+            mcp23018_status = i2c_start(I2C_ADDR_WRITE);        if (mcp23018_status) goto out;
+            mcp23018_status = i2c_write(GPIOA);                 if (mcp23018_status) goto out;
+            mcp23018_status = i2c_write( 0xFF & ~(1<<row)
+                                  & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
+                              );                                if (mcp23018_status) goto out;
+        out:
+            i2c_stop();
+        }
+    } else {
+        // select on teensy
+        // Output low(DDR:1, PORT:0) to select
+        switch (row) {
+            case 7:
+                DDRB  |= (1<<0);
+                PORTB &= ~(1<<0);
+                break;
+            case 8:
+                DDRB  |= (1<<1);
+                PORTB &= ~(1<<1);
+                break;
+            case 9:
+                DDRB  |= (1<<2);
+                PORTB &= ~(1<<2);
+                break;
+            case 10:
+                DDRB  |= (1<<3);
+                PORTB &= ~(1<<3);
+                break;
+            case 11:
+                DDRD  |= (1<<2);
+                PORTD &= ~(1<<3);
+                break;
+            case 12:
+                DDRD  |= (1<<3);
+                PORTD &= ~(1<<3);
+                break;
+            case 13:
+                DDRC  |= (1<<6);
+                PORTC &= ~(1<<6);
+                break;
+        }
+    }
+}
diff --git a/keyboard/ergodox/twimaster.c b/keyboard/ergodox/twimaster.c
new file mode 100755 (executable)
index 0000000..f91c08e
--- /dev/null
@@ -0,0 +1,208 @@
+/*************************************************************************
+* Title:    I2C master library using hardware TWI interface
+* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
+* File:     $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
+* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
+* Target:   any AVR device with hardware TWI 
+* Usage:    API compatible with I2C Software Library i2cmaster.h
+**************************************************************************/
+#include <inttypes.h>
+#include <compat/twi.h>
+
+#include <i2cmaster.h>
+
+
+/* define CPU frequency in Mhz here if not defined in Makefile */
+#ifndef F_CPU
+#define F_CPU 16000000UL
+#endif
+
+/* I2C clock in Hz */
+#define SCL_CLOCK  400000L
+
+
+/*************************************************************************
+ Initialization of the I2C bus interface. Need to be called only once
+*************************************************************************/
+void i2c_init(void)
+{
+  /* initialize TWI clock
+   * minimal values in Bit Rate Register (TWBR) and minimal Prescaler
+   * bits in the TWI Status Register should give us maximal possible
+   * I2C bus speed - about 444 kHz
+   *
+   * for more details, see 20.5.2 in ATmega16/32 secification
+   */
+  
+  TWSR = 0;     /* no prescaler */
+  TWBR = 10;    /* must be >= 10 for stable operation */
+
+}/* i2c_init */
+
+
+/*************************************************************************     
+  Issues a start condition and sends address and transfer direction.
+  return 0 = device accessible, 1= failed to access device
+*************************************************************************/
+unsigned char i2c_start(unsigned char address)
+{
+    uint8_t   twst;
+
+       // send START condition
+       TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+
+       // wait until transmission completed
+       while(!(TWCR & (1<<TWINT)));
+
+       // check value of TWI Status Register. Mask prescaler bits.
+       twst = TW_STATUS & 0xF8;
+       if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
+
+       // send device address
+       TWDR = address;
+       TWCR = (1<<TWINT) | (1<<TWEN);
+
+       // wail until transmission completed and ACK/NACK has been received
+       while(!(TWCR & (1<<TWINT)));
+
+       // check value of TWI Status Register. Mask prescaler bits.
+       twst = TW_STATUS & 0xF8;
+       if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
+
+       return 0;
+
+}/* i2c_start */
+
+
+/*************************************************************************
+ Issues a start condition and sends address and transfer direction.
+ If device is busy, use ack polling to wait until device is ready
+ Input:   address and transfer direction of I2C device
+*************************************************************************/
+void i2c_start_wait(unsigned char address)
+{
+    uint8_t   twst;
+
+
+    while ( 1 )
+    {
+           // send START condition
+           TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+    
+       // wait until transmission completed
+       while(!(TWCR & (1<<TWINT)));
+    
+       // check value of TWI Status Register. Mask prescaler bits.
+       twst = TW_STATUS & 0xF8;
+       if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
+    
+       // send device address
+       TWDR = address;
+       TWCR = (1<<TWINT) | (1<<TWEN);
+    
+       // wail until transmission completed
+       while(!(TWCR & (1<<TWINT)));
+    
+       // check value of TWI Status Register. Mask prescaler bits.
+       twst = TW_STATUS & 0xF8;
+       if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
+       {           
+           /* device busy, send stop condition to terminate write operation */
+               TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+               
+               // wait until stop condition is executed and bus released
+               while(TWCR & (1<<TWSTO));
+               
+           continue;
+       }
+       //if( twst != TW_MT_SLA_ACK) return 1;
+       break;
+     }
+
+}/* i2c_start_wait */
+
+
+/*************************************************************************
+ Issues a repeated start condition and sends address and transfer direction 
+
+ Input:   address and transfer direction of I2C device
+ Return:  0 device accessible
+          1 failed to access device
+*************************************************************************/
+unsigned char i2c_rep_start(unsigned char address)
+{
+    return i2c_start( address );
+
+}/* i2c_rep_start */
+
+
+/*************************************************************************
+ Terminates the data transfer and releases the I2C bus
+*************************************************************************/
+void i2c_stop(void)
+{
+    /* send stop condition */
+       TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+       
+       // wait until stop condition is executed and bus released
+       while(TWCR & (1<<TWSTO));
+
+}/* i2c_stop */
+
+
+/*************************************************************************
+  Send one byte to I2C device
+  
+  Input:    byte to be transfered
+  Return:   0 write successful 
+            1 write failed
+*************************************************************************/
+unsigned char i2c_write( unsigned char data )
+{      
+    uint8_t   twst;
+    
+       // send data to the previously addressed device
+       TWDR = data;
+       TWCR = (1<<TWINT) | (1<<TWEN);
+
+       // wait until transmission completed
+       while(!(TWCR & (1<<TWINT)));
+
+       // check value of TWI Status Register. Mask prescaler bits
+       twst = TW_STATUS & 0xF8;
+       if( twst != TW_MT_DATA_ACK) return 1;
+       return 0;
+
+}/* i2c_write */
+
+
+/*************************************************************************
+ Read one byte from the I2C device, request more data from device 
+ Return:  byte read from I2C device
+*************************************************************************/
+unsigned char i2c_readAck(void)
+{
+       TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
+       while(!(TWCR & (1<<TWINT)));    
+
+    return TWDR;
+
+}/* i2c_readAck */
+
+
+/*************************************************************************
+ Read one byte from the I2C device, read is followed by a stop condition 
+ Return:  byte read from I2C device
+*************************************************************************/
+unsigned char i2c_readNak(void)
+{
+       TWCR = (1<<TWINT) | (1<<TWEN);
+       while(!(TWCR & (1<<TWINT)));
+       
+    return TWDR;
+
+}/* i2c_readNak */
Imprint / Impressum