]> git.donarmstrong.com Git - tmk_firmware.git/commitdiff
Implementation for Ergodox project
authorOleg Kostyuk <cub.uanic@gmail.com>
Sat, 10 Aug 2013 19:57:01 +0000 (22:57 +0300)
committerOleg Kostyuk <cub.uanic@gmail.com>
Wed, 4 Sep 2013 20:55:43 +0000 (23:55 +0300)
14 files changed:
keyboard/ergodox/Makefile.pjrc [new file with mode: 0644]
keyboard/ergodox/TODO [new file with mode: 0644]
keyboard/ergodox/config.h [new file with mode: 0644]
keyboard/ergodox/ergodox.c [new file with mode: 0644]
keyboard/ergodox/ergodox.h [new file with mode: 0644]
keyboard/ergodox/i2cmaster.h [new file with mode: 0644]
keyboard/ergodox/keymap.c [new file with mode: 0644]
keyboard/ergodox/keymap_colemak.h [new file with mode: 0644]
keyboard/ergodox/keymap_cub.h [new file with mode: 0644]
keyboard/ergodox/keymap_dvorak.h [new file with mode: 0644]
keyboard/ergodox/keymap_workman.h [new file with mode: 0644]
keyboard/ergodox/led.c [new file with mode: 0644]
keyboard/ergodox/matrix.c [new file with mode: 0644]
keyboard/ergodox/twimaster.c [new file with mode: 0644]

diff --git a/keyboard/ergodox/Makefile.pjrc b/keyboard/ergodox/Makefile.pjrc
new file mode 100644 (file)
index 0000000..6377252
--- /dev/null
@@ -0,0 +1,115 @@
+#----------------------------------------------------------------------------
+# 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
+TOP_DIR = ../..
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC =  keymap.c \
+       matrix.c \
+       led.c \
+       ergodox.c \
+       twimaster.c
+
+CONFIG_H = config.h
+
+
+# MCU name, you MUST set this to match the board you are using
+# type "make clean" after changing this, so all files will be rebuilt
+MCU = atmega32u4
+#MCU = at90usb1286
+
+
+# Processor frequency.
+#   Normally the first thing your program should do is set the clock prescaler,
+#   so your program will run at the correct speed.  You should also set this
+#   variable to same clock speed.  The _delay_ms() macro uses this, and many
+#   examples use this variable to calculate timings.  Do not add a "UL" here.
+F_CPU = 16000000
+
+
+# Boot Section Size in *bytes*
+#   Teensy halfKay   512
+#   Atmel DFU loader 4096
+#   LUFA bootloader  4096
+OPT_DEFS += -DBOOTLOADER_SIZE=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 += $(TOP_DIR)
+
+include $(TOP_DIR)/protocol/pjrc.mk
+include $(TOP_DIR)/common.mk
+include $(TOP_DIR)/rules.mk
+
+dvorak: OPT_DEFS += -DKEYMAP_DVORAK
+dvorak: all
+
+colemak: OPT_DEFS += -DKEYMAP_COLEMAK
+colemak: all
+
+workman: OPT_DEFS += -DKEYMAP_WORKMAN
+workman: all
+
+cub: OPT_DEFS += -DKEYMAP_CUB
+cub: all
+
+
diff --git a/keyboard/ergodox/TODO b/keyboard/ergodox/TODO
new file mode 100644 (file)
index 0000000..d630c73
--- /dev/null
@@ -0,0 +1,10 @@
+1. Flash led on ~Ln keypress (for now it works only on +Ln)
+2. Flash NumLock led only when "numpad" layer is active
+3. Command (in terms of IS_COMMAND) to switch to no-leds mode
+4. Increase count of ACTION keys
+5. Check how it works with ACTION/TAP keys (layerN+key or modifier+key)
+6. Fix command_state() onboard led:
+    it should flash only when kbd in some specific mode (CONSOLE || MOUSE)
+7. Fix Right TEENSY key (for now it locks kbd & system)
+8. Cleanup everything, add conditionals (ifdef/ifndef), push to github
+
diff --git a/keyboard/ergodox/config.h b/keyboard/ergodox/config.h
new file mode 100644 (file)
index 0000000..d2ca7ea
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+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      0x1111
+#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 if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE    5
+
+/* 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_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
+
+#endif
diff --git a/keyboard/ergodox/ergodox.c b/keyboard/ergodox/ergodox.c
new file mode 100644 (file)
index 0000000..8aed78e
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+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;
+
+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);
+
+    // blink leds
+    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) {
+    uint8_t err = 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
+    err = i2c_start(I2C_ADDR_WRITE);    if (err) goto out;
+    err = i2c_write(IODIRA);            if (err) goto out;
+    err = i2c_write(0b00000000);        if (err) goto out;
+    err = i2c_write(0b00111111);        if (err) goto out;
+    i2c_stop();
+    // set pull-up
+    // - unused  : on  : 1
+    // - input   : on  : 1
+    // - driving : off : 0
+    err = i2c_start(I2C_ADDR_WRITE);    if (err) goto out;
+    err = i2c_write(GPPUA);             if (err) goto out;
+    err = i2c_write(0b00000000);        if (err) goto out;
+    err = i2c_write(0b00111111);        if (err) goto out;
+    i2c_stop();
+
+    // set logical value (doesn't matter on inputs)
+    // - unused  : hi-Z : 1
+    // - input   : hi-Z : 1
+    // - driving : hi-Z : 1
+    err = i2c_start(I2C_ADDR_WRITE);    if (err) goto out;
+    err = i2c_write(OLATA);             if (err) goto out;
+    err = i2c_write(0b11111111
+            & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
+          );                            if (err) goto out;
+    err = i2c_write(0b11111111
+            & ~(ergodox_left_led_2<<LEFT_LED_2_SHIFT)
+            & ~(ergodox_left_led_1<<LEFT_LED_1_SHIFT)
+          );                            if (err) goto out;
+
+out:
+    i2c_stop();
+    return err;
+}
+
diff --git a/keyboard/ergodox/ergodox.h b/keyboard/ergodox/ergodox.h
new file mode 100644 (file)
index 0000000..d962368
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+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
+
+void init_ergodox(void);
+uint8_t init_mcp23018(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_left_leds_update(void)  { init_mcp23018(); }
+
+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 100644 (file)
index 0000000..70f51fd
--- /dev/null
@@ -0,0 +1,178 @@
+#ifndef _I2CMASTER_H\r
+#define _I2CMASTER_H   1\r
+/************************************************************************* \r
+* Title:    C include file for the I2C master interface \r
+*           (i2cmaster.S or twimaster.c)\r
+* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury\r
+* File:     $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $\r
+* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3\r
+* Target:   any AVR device\r
+* Usage:    see Doxygen manual\r
+**************************************************************************/\r
+\r
+#ifdef DOXYGEN\r
+/**\r
+ @defgroup pfleury_ic2master I2C Master library\r
+ @code #include <i2cmaster.h> @endcode\r
+  \r
+ @brief I2C (TWI) Master Software Library\r
+\r
+ Basic routines for communicating with I2C slave devices. This single master \r
+ implementation is limited to one bus master on the I2C bus. \r
+\r
+ This I2c library is implemented as a compact assembler software implementation of the I2C protocol \r
+ which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).\r
+ Since the API for these two implementations is exactly the same, an application can be linked either against the\r
+ software I2C implementation or the hardware I2C implementation.\r
+\r
+ Use 4.7k pull-up resistor on the SDA and SCL pin.\r
\r
+ Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module \r
+ i2cmaster.S to your target when using the software I2C implementation ! \r
\r
+ Adjust the  CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.\r
+\r
+ @note \r
+    The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted \r
+    to GNU assembler and AVR-GCC C call interface.\r
+    Replaced the incorrect quarter period delays found in AVR300 with \r
+    half period delays. \r
+    \r
+ @author Peter Fleury pfleury@gmx.ch  http://jump.to/fleury\r
+\r
+ @par API Usage Example\r
+  The following code shows typical usage of this library, see example test_i2cmaster.c\r
+\r
+ @code\r
+\r
+ #include <i2cmaster.h>\r
+\r
+\r
+ #define Dev24C02  0xA2      // device address of EEPROM 24C02, see datasheet\r
+\r
+ int main(void)\r
+ {\r
+     unsigned char ret;\r
+\r
+     i2c_init();                             // initialize I2C library\r
+\r
+     // write 0x75 to EEPROM address 5 (Byte Write) \r
+     i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode\r
+     i2c_write(0x05);                        // write address = 5\r
+     i2c_write(0x75);                        // write value 0x75 to EEPROM\r
+     i2c_stop();                             // set stop conditon = release bus\r
+\r
+\r
+     // read previously written value back from EEPROM address 5 \r
+     i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode\r
+\r
+     i2c_write(0x05);                        // write address = 5\r
+     i2c_rep_start(Dev24C02+I2C_READ);       // set device address and read mode\r
+\r
+     ret = i2c_readNak();                    // read one byte from EEPROM\r
+     i2c_stop();\r
+\r
+     for(;;);\r
+ }\r
+ @endcode\r
+\r
+*/\r
+#endif /* DOXYGEN */\r
+\r
+/**@{*/\r
+\r
+#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304\r
+#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"\r
+#endif\r
+\r
+#include <avr/io.h>\r
+\r
+/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */\r
+#define I2C_READ    1\r
+\r
+/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */\r
+#define I2C_WRITE   0\r
+\r
+\r
+/**\r
+ @brief initialize the I2C master interace. Need to be called only once \r
+ @param  void\r
+ @return none\r
+ */\r
+extern void i2c_init(void);\r
+\r
+\r
+/** \r
+ @brief Terminates the data transfer and releases the I2C bus \r
+ @param void\r
+ @return none\r
+ */\r
+extern void i2c_stop(void);\r
+\r
+\r
+/** \r
+ @brief Issues a start condition and sends address and transfer direction \r
+  \r
+ @param    addr address and transfer direction of I2C device\r
+ @retval   0   device accessible \r
+ @retval   1   failed to access device \r
+ */\r
+extern unsigned char i2c_start(unsigned char addr);\r
+\r
+\r
+/**\r
+ @brief Issues a repeated start condition and sends address and transfer direction \r
+\r
+ @param   addr address and transfer direction of I2C device\r
+ @retval  0 device accessible\r
+ @retval  1 failed to access device\r
+ */\r
+extern unsigned char i2c_rep_start(unsigned char addr);\r
+\r
+\r
+/**\r
+ @brief Issues a start condition and sends address and transfer direction \r
+   \r
+ If device is busy, use ack polling to wait until device ready \r
+ @param    addr address and transfer direction of I2C device\r
+ @return   none\r
+ */\r
+extern void i2c_start_wait(unsigned char addr);\r
+\r
\r
+/**\r
+ @brief Send one byte to I2C device\r
+ @param    data  byte to be transfered\r
+ @retval   0 write successful\r
+ @retval   1 write failed\r
+ */\r
+extern unsigned char i2c_write(unsigned char data);\r
+\r
+\r
+/**\r
+ @brief    read one byte from the I2C device, request more data from device \r
+ @return   byte read from I2C device\r
+ */\r
+extern unsigned char i2c_readAck(void);\r
+\r
+/**\r
+ @brief    read one byte from the I2C device, read is followed by a stop condition \r
+ @return   byte read from I2C device\r
+ */\r
+extern unsigned char i2c_readNak(void);\r
+\r
+/** \r
+ @brief    read one byte from the I2C device\r
\r
+ Implemented as a macro, which calls either i2c_readAck or i2c_readNak\r
\r
+ @param    ack 1 send ack, request more data from device<br>\r
+               0 send nak, read is followed by a stop condition \r
+ @return   byte read from I2C device\r
+ */\r
+extern unsigned char i2c_read(unsigned char ack);\r
+#define i2c_read(ack)  (ack) ? i2c_readAck() : i2c_readNak(); \r
+\r
+\r
+/**@}*/\r
+#endif\r
diff --git a/keyboard/ergodox/keymap.c b/keyboard/ergodox/keymap.c
new file mode 100644 (file)
index 0000000..fb553d0
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+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 <stdbool.h>
+#include <avr/pgmspace.h>
+#include <util/delay.h>
+#include "keycode.h"
+#include "action.h"
+#include "action_code.h"
+#include "action_macro.h"
+#include "bootloader.h"
+#include "report.h"
+#include "host.h"
+#include "print.h"
+#include "debug.h"
+#include "keymap.h"
+#include "ergodox.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   }    \
+   }
+
+#if defined(KEYMAP_DVORAK)
+#include "keymap_dvorak.h"
+#elif defined(KEYMAP_COLEMAK)
+#include "keymap_colemak.h"
+#elif defined(KEYMAP_WORKMAN)
+#include "keymap_workman.h"
+#elif defined(KEYMAP_CUB)
+#include "keymap_cub.h"
+#else
+
+static 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
+             SLCK,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
+ */
+static 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 - push Layer2
+    ACTION_LAYER_SET(3, ON_PRESS),                  // FN3 - push Layer3
+    ACTION_LAYER_SET(0, ON_PRESS),                  // FN4 - push 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");
+    }
+}
+
+#endif
+
+
+#define KEYMAPS_SIZE    (sizeof(keymaps) / sizeof(keymaps[0]))
+#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0]))
+
+/* translates key to keycode */
+uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
+{
+    if (layer < KEYMAPS_SIZE) {
+        return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
+    } else {
+        // fall back to layer 0
+        return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]);
+    }
+}
+
+/* translates Fn keycode to action */
+action_t keymap_fn_to_action(uint8_t keycode)
+{
+    action_t action;
+    if (FN_INDEX(keycode) < FN_ACTIONS_SIZE) {
+        action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
+    } else {
+        action.code = ACTION_NO;
+    }
+    return action;
+}
+
diff --git a/keyboard/ergodox/keymap_colemak.h b/keyboard/ergodox/keymap_colemak.h
new file mode 100644 (file)
index 0000000..4e5565e
--- /dev/null
@@ -0,0 +1,4 @@
+#error Colemak layout is not defined yet
+static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+};
+static const uint16_t PROGMEM fn_actions[] = {};
diff --git a/keyboard/ergodox/keymap_cub.h b/keyboard/ergodox/keymap_cub.h
new file mode 100644 (file)
index 0000000..178d10f
--- /dev/null
@@ -0,0 +1,227 @@
+static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+    /* Keymap 0: Default Layer
+     *
+     * ,--------------------------------------------------.           ,--------------------------------------------------.
+     * |   ~    |   1  |   2  |   3  |   4  |   5  |   \  |           |   '  |   6  |   7  |   8  |   9  |   0  |   =    |
+     * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+     * | Tab    |   Q  |   W  |   E  |   R  |   T  | ~Fn1 |           | ~Fn3 |   Y  |   U  |   I  |   O  |   P  |   [    |
+     * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+     * | LShift |   A  |   S  |   D  |   F  |   G  |------|           |------|   H  |   J  |   K  |   L  |   ;  | RShift |
+     * |--------+------+------+------+------+------|  Fn0 |           | ~Fn4 |------+------+------+------+------+--------|
+     * | LCtrl  |   Z  |   X  |   C  |   V  |   B  |      |           |      |   N  |   M  |   ,  |   .  |   /  | RCtrl  |
+     * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+     *   | ~Fn1 | ~Fn2 | Caps | LAlt | LGui |                                       |  Lft |  Up  |  Dn  | Rght | ~Fn4 |
+     *   `----------------------------------'                                       `----------------------------------'
+     *                                        ,-------------.       ,-------------.
+     *                                        | +Fn2 | Home |       | PgUp | Del  |
+     *                                 ,------|------|------|       |------+------+------.
+     *                                 |      |      |  End |       | PgDn |      |      |
+     *                                 | BkSp |  ESC |------|       |------| Enter| Space|
+     *                                 |      |      |  Spc |       | Ins  |      |      |
+     *                                 `--------------------'       `--------------------'
+     */
+
+    KEYMAP(  // layout: layer 0: default
+        // left hand
+        GRV, 1,   2,   3,   4,   5,   BSLS,
+        TAB, Q,   W,   E,   R,   T,   FN1,
+        LSFT,A,   S,   D,   F,   G,
+        LCTL,Z,   X,   C,   V,   B,   FN0,
+        FN1, FN6, CAPS,LALT,LGUI,
+                                      FN2, HOME,
+                                           END,
+                                 BSPC,ESC, SPC,
+        // right hand
+             QUOT,6,   7,   8,   9,   0,   EQL,
+             FN3, Y,   U,   I,   O,   P,   LBRC,
+                  H,   J,   K,   L,   SCLN,RSFT,
+             FN4, N,   M,   COMM,DOT, SLSH,RCTL,
+                       LEFT,UP,  DOWN,RGHT,FN4,
+        PGUP,DEL,
+        PGDN,
+        INS, ENT, SPC
+    ),
+
+    KEYMAP(  // layout: layer 1: F-keys instead of numbers
+        // left hand
+        TRNS,F1,  F2,  F3,  F4,  F5,  F6,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+        TRNS,TRNS,TRNS,LALT,LGUI,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 LCTL,LSFT,TRNS,
+        // right hand
+             F7,  F8,  F9,  F10, F11, F12, MINS,
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,RBRC,
+                  TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+             TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+                       RGUI,RALT,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,RSFT,RCTL
+    ),
+
+    KEYMAP(  // layout: layer 2: mouse + numpad
+        // left hand
+        TRNS,NO,  NO,  NO,  NO,  PAUS,PSCR,
+        TRNS,WH_L,WH_U,WH_D,WH_R,BTN2,TRNS,
+        TRNS,MS_L,MS_U,MS_D,MS_R,BTN1,
+        TRNS,NO,  NO,  NO,  NO,  BTN3,TRNS,
+        TRNS,TRNS,TRNS,TRNS,TRNS,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 TRNS,TRNS,TRNS,
+        // right hand
+             SLCK,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
+    ),
+
+    KEYMAP(  // layout: layer 3: F-keys only
+        // left hand
+        TRNS,NO,  NO,  NO,  NO,  NO,  NO,  
+        TRNS,F13, F14, F15, F16, NO,  TRNS,
+        TRNS,F17, F18, F19, F20, NO,  
+        TRNS,F21, F22, F23, F24, 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,  TRNS,
+                  NO,  F5,  F6,  F7,  F8,  TRNS,
+             TRNS,NO,  F9,  F10, F11, F12, TRNS,
+                       RGUI,RALT,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,RSFT,RCTL
+    ),
+
+    KEYMAP(  // layout: layer 4: F-keys + cursor
+        // left hand
+        TRNS,F1,  F2,  F3,  F4,  F5,  F6,
+        FN7, NO,  PGUP,UP,  PGDN,PGUP,TRNS,
+        TRNS,NO,  LEFT,DOWN,RGHT,PGDN,
+        TRNS,NO,  NO,  END, HOME,NO,  TRNS,
+        FN5, TRNS,TRNS,LALT,LGUI,
+                                      TRNS,TRNS,
+                                           TRNS,
+                                 LCTL,LSFT,TRNS,
+        // right hand
+             F7,  F8,  F9,  F10, F11, F12, MINS,
+             TRNS,PGUP,PGUP,UP,  PGDN,NO,  FN7,
+                  PGDN,LEFT,DOWN,RGHT,NO,  TRNS,
+             TRNS,NO,  HOME,END, NO,  NO,  TRNS,
+                       RGUI,RALT,TRNS,TRNS,TRNS,
+        TRNS,TRNS,
+        TRNS,
+        TRNS,RSFT,RCTL
+    ),
+
+    KEYMAP(  // layout: layer 5: Workman layout
+        // 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(  // layout: layer N: transparent on edges, 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(  // layout: layer N: 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
+ */
+static const uint16_t PROGMEM fn_actions[] = {
+    ACTION_DEFAULT_LAYER_SET(0),                    // FN0 - switch to Layer0
+    ACTION_LAYER_MOMENTARY(1),                      // FN1 - push Layer1
+    ACTION_DEFAULT_LAYER_SET(2),                    // FN2 - switch to Layer2
+    ACTION_LAYER_MOMENTARY(3),                      // FN3 - push Layer3
+    ACTION_LAYER_MOMENTARY(4),                      // FN4 - push Layer4
+    ACTION_DEFAULT_LAYER_SET(5),                    // FN5 - switch to Layer5
+    ACTION_LAYER_MOMENTARY(2),                      // FN6 - push Layer2
+    ACTION_FUNCTION(TEENSY_KEY),                    // FN7 - Teensy key
+};
+
+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_dvorak.h b/keyboard/ergodox/keymap_dvorak.h
new file mode 100644 (file)
index 0000000..198709c
--- /dev/null
@@ -0,0 +1,4 @@
+#error Dvorak layout is not defined yet
+static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+};
+static const uint16_t PROGMEM fn_actions[] = {};
diff --git a/keyboard/ergodox/keymap_workman.h b/keyboard/ergodox/keymap_workman.h
new file mode 100644 (file)
index 0000000..b157065
--- /dev/null
@@ -0,0 +1,4 @@
+#error Workman layout is not defined yet
+static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+};
+static const uint16_t PROGMEM fn_actions[] = {};
diff --git a/keyboard/ergodox/led.c b/keyboard/ergodox/led.c
new file mode 100644 (file)
index 0000000..55fb4ff
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+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
+#ifdef 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 100644 (file)
index 0000000..b0ba1c0
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+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"
+
+#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 mcp23018_status, uint8_t row);
+static void init_cols(void);
+static void unselect_rows(uint8_t mcp23018_status);
+static void select_row(uint8_t mcp23018_status, uint8_t row);
+
+
+inline
+uint8_t matrix_rows(void)
+{
+    return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+    return MATRIX_COLS;
+}
+
+void matrix_init(void)
+{
+    // initialize row and col
+    init_ergodox();
+    uint8_t mcp23018_status;
+    mcp23018_status = init_mcp23018();
+    unselect_rows(mcp23018_status);
+    init_cols();
+
+    // initialize matrix state: all keys off
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+        matrix[i] = 0;
+        matrix_debouncing[i] = 0;
+    }
+}
+
+uint8_t matrix_scan(void)
+{
+#ifdef KEYMAP_CUB
+    uint8_t layer = biton32(layer_state);
+
+    if (layer == 1) {
+        ergodox_left_led_1_on();
+        ergodox_left_led_2_off();
+        ergodox_left_led_3_off();
+    } else if (layer == 2) {
+        ergodox_left_led_1_off();
+        ergodox_left_led_2_on();
+        ergodox_left_led_3_off();
+    } else if (layer == 3) {
+        ergodox_left_led_1_off();
+        ergodox_left_led_2_off();
+        ergodox_left_led_3_on();
+    } else if (layer == 4) {
+        ergodox_left_led_1_on();
+        ergodox_left_led_2_off();
+        ergodox_left_led_3_on();
+    } else if (layer == 5) {
+        ergodox_left_led_1_on();
+        ergodox_left_led_2_on();
+        ergodox_left_led_3_off();
+    } else if (layer == 6) {
+        ergodox_left_led_1_off();
+        ergodox_left_led_2_on();
+        ergodox_left_led_3_on();
+    } else if (layer == 7) {
+        ergodox_left_led_1_on();
+        ergodox_left_led_2_on();
+        ergodox_left_led_3_on();
+    } else {
+        ergodox_left_led_1_off();
+        ergodox_left_led_2_off();
+        ergodox_left_led_3_off();
+    }
+
+    // not actually needed because we already calling init_mcp23018() in next line
+    // ergodox_left_leds_update();
+
+#endif
+
+    uint8_t mcp23018_status = init_mcp23018();
+
+    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+        select_row(mcp23018_status, i);
+        _delay_us(30);  // without this wait read unstable value.
+        matrix_row_t cols = read_cols(mcp23018_status, i);
+        if (matrix_debouncing[i] != cols) {
+            matrix_debouncing[i] = cols;
+            if (debouncing) {
+                debug("bounce!: "); debug_hex(debouncing); debug("\n");
+            }
+            debouncing = DEBOUNCE;
+        }
+        unselect_rows(mcp23018_status);
+    }
+
+    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 mcp23018_status, uint8_t row)
+{
+    if (row < 7) {
+        if (mcp23018_status) { // if there was an error
+            return 0;
+        } else {
+            uint8_t data = 0;
+            uint8_t err = 0x20;
+            err = i2c_start(I2C_ADDR_WRITE);    if (err) goto out;
+            err = i2c_write(GPIOB);             if (err) goto out;
+            err = i2c_start(I2C_ADDR_READ);     if (err) goto out;
+            data = i2c_readNak();
+            data = ~data;
+        out:
+            i2c_stop();
+            return data;
+        }
+    } else {
+        // 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(uint8_t mcp23018_status)
+{
+    // unselect on mcp23018
+    if (mcp23018_status) { // if there was an error
+        // do nothing
+    } else {
+        // set all rows hi-Z : 1
+        uint8_t err = 0x20;
+        err = i2c_start(I2C_ADDR_WRITE);    if (err) goto out;
+        err = i2c_write(GPIOA);             if (err) goto out;
+        err = i2c_write( 0xFF
+                & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
+              );                            if (err) 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 mcp23018_status, 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
+            uint8_t err = 0x20;
+            err = i2c_start(I2C_ADDR_WRITE);        if (err) goto out;
+            err = i2c_write(GPIOA);                 if (err) goto out;
+            err = i2c_write( 0xFF & ~(1<<row) 
+                    & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
+                  );                                if (err) 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 100644 (file)
index 0000000..f0d850c
--- /dev/null
@@ -0,0 +1,202 @@
+/*************************************************************************\r
+* Title:    I2C master library using hardware TWI interface\r
+* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury\r
+* File:     $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $\r
+* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3\r
+* Target:   any AVR device with hardware TWI \r
+* Usage:    API compatible with I2C Software Library i2cmaster.h\r
+**************************************************************************/\r
+#include <inttypes.h>\r
+#include <compat/twi.h>\r
+\r
+#include <i2cmaster.h>\r
+\r
+\r
+/* define CPU frequency in Mhz here if not defined in Makefile */\r
+#ifndef F_CPU\r
+#define F_CPU 4000000UL\r
+#endif\r
+\r
+/* I2C clock in Hz */\r
+#define SCL_CLOCK  100000L\r
+\r
+\r
+/*************************************************************************\r
+ Initialization of the I2C bus interface. Need to be called only once\r
+*************************************************************************/\r
+void i2c_init(void)\r
+{\r
+  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */\r
+  \r
+  TWSR = 0;                         /* no prescaler */\r
+  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */\r
+\r
+}/* i2c_init */\r
+\r
+\r
+/*************************************************************************     \r
+  Issues a start condition and sends address and transfer direction.\r
+  return 0 = device accessible, 1= failed to access device\r
+*************************************************************************/\r
+unsigned char i2c_start(unsigned char address)\r
+{\r
+    uint8_t   twst;\r
+\r
+       // send START condition\r
+       TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);\r
+\r
+       // wait until transmission completed\r
+       while(!(TWCR & (1<<TWINT)));\r
+\r
+       // check value of TWI Status Register. Mask prescaler bits.\r
+       twst = TW_STATUS & 0xF8;\r
+       if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;\r
+\r
+       // send device address\r
+       TWDR = address;\r
+       TWCR = (1<<TWINT) | (1<<TWEN);\r
+\r
+       // wail until transmission completed and ACK/NACK has been received\r
+       while(!(TWCR & (1<<TWINT)));\r
+\r
+       // check value of TWI Status Register. Mask prescaler bits.\r
+       twst = TW_STATUS & 0xF8;\r
+       if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;\r
+\r
+       return 0;\r
+\r
+}/* i2c_start */\r
+\r
+\r
+/*************************************************************************\r
+ Issues a start condition and sends address and transfer direction.\r
+ If device is busy, use ack polling to wait until device is ready\r
\r
+ Input:   address and transfer direction of I2C device\r
+*************************************************************************/\r
+void i2c_start_wait(unsigned char address)\r
+{\r
+    uint8_t   twst;\r
+\r
+\r
+    while ( 1 )\r
+    {\r
+           // send START condition\r
+           TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);\r
+    \r
+       // wait until transmission completed\r
+       while(!(TWCR & (1<<TWINT)));\r
+    \r
+       // check value of TWI Status Register. Mask prescaler bits.\r
+       twst = TW_STATUS & 0xF8;\r
+       if ( (twst != TW_START) && (twst != TW_REP_START)) continue;\r
+    \r
+       // send device address\r
+       TWDR = address;\r
+       TWCR = (1<<TWINT) | (1<<TWEN);\r
+    \r
+       // wail until transmission completed\r
+       while(!(TWCR & (1<<TWINT)));\r
+    \r
+       // check value of TWI Status Register. Mask prescaler bits.\r
+       twst = TW_STATUS & 0xF8;\r
+       if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) \r
+       {           \r
+           /* device busy, send stop condition to terminate write operation */\r
+               TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);\r
+               \r
+               // wait until stop condition is executed and bus released\r
+               while(TWCR & (1<<TWSTO));\r
+               \r
+           continue;\r
+       }\r
+       //if( twst != TW_MT_SLA_ACK) return 1;\r
+       break;\r
+     }\r
+\r
+}/* i2c_start_wait */\r
+\r
+\r
+/*************************************************************************\r
+ Issues a repeated start condition and sends address and transfer direction \r
+\r
+ Input:   address and transfer direction of I2C device\r
\r
+ Return:  0 device accessible\r
+          1 failed to access device\r
+*************************************************************************/\r
+unsigned char i2c_rep_start(unsigned char address)\r
+{\r
+    return i2c_start( address );\r
+\r
+}/* i2c_rep_start */\r
+\r
+\r
+/*************************************************************************\r
+ Terminates the data transfer and releases the I2C bus\r
+*************************************************************************/\r
+void i2c_stop(void)\r
+{\r
+    /* send stop condition */\r
+       TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);\r
+       \r
+       // wait until stop condition is executed and bus released\r
+       while(TWCR & (1<<TWSTO));\r
+\r
+}/* i2c_stop */\r
+\r
+\r
+/*************************************************************************\r
+  Send one byte to I2C device\r
+  \r
+  Input:    byte to be transfered\r
+  Return:   0 write successful \r
+            1 write failed\r
+*************************************************************************/\r
+unsigned char i2c_write( unsigned char data )\r
+{      \r
+    uint8_t   twst;\r
+    \r
+       // send data to the previously addressed device\r
+       TWDR = data;\r
+       TWCR = (1<<TWINT) | (1<<TWEN);\r
+\r
+       // wait until transmission completed\r
+       while(!(TWCR & (1<<TWINT)));\r
+\r
+       // check value of TWI Status Register. Mask prescaler bits\r
+       twst = TW_STATUS & 0xF8;\r
+       if( twst != TW_MT_DATA_ACK) return 1;\r
+       return 0;\r
+\r
+}/* i2c_write */\r
+\r
+\r
+/*************************************************************************\r
+ Read one byte from the I2C device, request more data from device \r
\r
+ Return:  byte read from I2C device\r
+*************************************************************************/\r
+unsigned char i2c_readAck(void)\r
+{\r
+       TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);\r
+       while(!(TWCR & (1<<TWINT)));    \r
+\r
+    return TWDR;\r
+\r
+}/* i2c_readAck */\r
+\r
+\r
+/*************************************************************************\r
+ Read one byte from the I2C device, read is followed by a stop condition \r
\r
+ Return:  byte read from I2C device\r
+*************************************************************************/\r
+unsigned char i2c_readNak(void)\r
+{\r
+       TWCR = (1<<TWINT) | (1<<TWEN);\r
+       while(!(TWCR & (1<<TWINT)));\r
+       \r
+    return TWDR;\r
+\r
+}/* i2c_readNak */\r