]> git.donarmstrong.com Git - qmk_firmware.git/commitdiff
added ergodox
authorJack Humbert <jack.humb@gmail.com>
Mon, 26 Oct 2015 20:32:37 +0000 (16:32 -0400)
committerJack Humbert <jack.humb@gmail.com>
Mon, 26 Oct 2015 20:32:37 +0000 (16:32 -0400)
17 files changed:
keyboard/ergodox/Makefile [new file with mode: 0644]
keyboard/ergodox/README.md [new file with mode: 0644]
keyboard/ergodox/backlight.c [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/keymaps/keymap_default.c [new file with mode: 0644]
keyboard/ergodox/matrix.c [new file with mode: 0644]
keyboard/ergodox/twimaster.c [new file with mode: 0644]
keyboard/planck/config.h
keyboard/planck/config_definitions.h [deleted file]
keyboard/planck/planck.c
quantum.mk
quantum/config_common.h [new file with mode: 0644]
quantum/keymap_common.c
quantum/matrix.c

diff --git a/keyboard/ergodox/Makefile b/keyboard/ergodox/Makefile
new file mode 100644 (file)
index 0000000..f71d096
--- /dev/null
@@ -0,0 +1,139 @@
+#----------------------------------------------------------------------------
+# 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
+
+
+# Directory common source filess exist
+TOP_DIR = ../..
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# # project specific files
+SRC = ergodox.c \
+       twimaster.c \
+       backlight.c 
+
+ifdef KEYMAP
+    SRC := keymaps/keymap_$(KEYMAP).c $(SRC)
+else
+    SRC := keymaps/keymap_default.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+#     This will define a symbol, F_CPU, in all source code files equal to the
+#     processor frequency in Hz. You can then use this symbol in your source code to
+#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+#     automatically to create a 32-bit value in your source code.
+#
+#     This will be an integer division of F_USB below, as it is sourced by
+#     F_USB after it has run through any CPU prescalers. Note that this value
+#     does not *change* the processor frequency - it should merely be updated to
+#     reflect the processor speed set externally so that the code can use accurate
+#     software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+#     This will define a symbol, F_USB, in all source code files equal to the
+#     input clock frequency (before any prescaling is performed) in Hz. This value may
+#     differ from F_CPU if prescaling is used on the latter, and is required as the
+#     raw input clock is fed directly to the PLL sections of the AVR for high speed
+#     clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+#     at the end, this will be done automatically to create a 32-bit value in your
+#     source code.
+#
+#     If no clock division is performed on the input clock inside the AVR (via the
+#     CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+#   Teensy halfKay   512
+#   Teensy++ halfKay 1024
+#   Atmel DFU loader 4096
+#   LUFA bootloader  4096
+#   USBaspLoader     2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+#   comment out to disable the options.
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes  # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes  # Audio control and System control(+450)
+CONSOLE_ENABLE = yes   # Console for debug(+400)
+COMMAND_ENABLE = yes    # Commands for debug and configuration
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+# SLEEP_LED_ENABLE = yes  # Breathing sleep LED during USB suspend
+# NKRO_ENABLE = yes            # USB Nkey Rollover - not yet supported in LUFA
+# BACKLIGHT_ENABLE = yes  # Enable keyboard backlight functionality
+# MIDI_ENABLE = YES            # MIDI controls
+# UNICODE_ENABLE = YES                 # Unicode
+# BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+
+# Optimize size but this may cause error "relocation truncated to fit"
+#EXTRALDFLAGS = -Wl,--relax
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TOP_DIR)
+
+include $(TOP_DIR)/quantum.mk
+
diff --git a/keyboard/ergodox/README.md b/keyboard/ergodox/README.md
new file mode 100644 (file)
index 0000000..bbbc735
--- /dev/null
@@ -0,0 +1,56 @@
+# 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
+
+Q: Where to get binaries?
+A:
+
+Q: Where to get sources?
+A:
+
+Q: How to compile?
+A:
+
+
+# Layouts
+
+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[]
+
diff --git a/keyboard/ergodox/backlight.c b/keyboard/ergodox/backlight.c
new file mode 100644 (file)
index 0000000..f69364b
--- /dev/null
@@ -0,0 +1,61 @@
+
+#include <avr/io.h>
+#include "backlight.h"
+
+#define CHANNEL OCR1C
+
+void backlight_init_ports()
+{
+
+    // Setup PB7 as output and output low.
+    DDRB |= (1<<7);
+    PORTB &= ~(1<<7);
+    
+    // Use full 16-bit resolution. 
+    ICR1 = 0xFFFF;
+
+    // I could write a wall of text here to explain... but TL;DW
+    // Go read the ATmega32u4 datasheet.
+    // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
+    
+    // Pin PB7 = OCR1C (Timer 1, Channel C)
+    // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
+    // (i.e. start high, go low when counter matches.)
+    // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
+    // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
+    
+    TCCR1A = _BV(COM1C1) | _BV(WGM11); // = 0b00001010;
+    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
+
+    backlight_init();
+}
+
+void backlight_set(uint8_t level)
+{
+    if ( level == 0 )
+    {
+        // Turn off PWM control on PB7, revert to output low.
+        TCCR1A &= ~(_BV(COM1C1));
+        CHANNEL = 0x0;
+        // Prevent backlight blink on lowest level
+        PORTB &= ~(_BV(PORTB7));
+    }
+    else if ( level == BACKLIGHT_LEVELS )
+    {
+        // Prevent backlight blink on lowest level
+        PORTB &= ~(_BV(PORTB7));
+        // Turn on PWM control of PB7
+        TCCR1A |= _BV(COM1C1);
+        // Set the brightness
+        CHANNEL = 0xFFFF;
+    }
+    else        
+    {
+        // Prevent backlight blink on lowest level
+        PORTB &= ~(_BV(PORTB7));
+        // Turn on PWM control of PB7
+        TCCR1A |= _BV(COM1C1);
+        // Set the brightness
+        CHANNEL = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
+    }
+}
\ No newline at end of file
diff --git a/keyboard/ergodox/config.h b/keyboard/ergodox/config.h
new file mode 100644 (file)
index 0000000..c8eaae6
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+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/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID       0xFEED
+#define PRODUCT_ID      0x1307
+#define DEVICE_VER      0x0001
+#define MANUFACTURER    ErgoDox EZ
+#define PRODUCT         ErgoDox EZ
+#define DESCRIPTION     t.m.k. keyboard firmware for Ergodox
+
+/* key matrix size */
+#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 COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
+#define ROWS (int []){ D0, D5, B5, B6 }
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE    2
+#define TAPPING_TERM    230
+#define TAPPING_TOGGLE  2
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+    keyboard_report->mods == (MOD_BIT(KC_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 100644 (file)
index 0000000..38e9b3a
--- /dev/null
@@ -0,0 +1,121 @@
+#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 * matrix_init_user(void) {
+
+};
+
+void * matrix_scan_user(void) {
+
+};
+
+void * matrix_init_kb(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);
+
+    ergodox_blink_all_leds();
+
+       if (matrix_init_user) {
+               (*matrix_init_user)();
+       }
+};
+
+void * matrix_scan_kb(void) {
+
+       if (matrix_scan_user) {
+               (*matrix_scan_user)();
+       }
+};
+
+
+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 100644 (file)
index 0000000..9d0691d
--- /dev/null
@@ -0,0 +1,145 @@
+#ifndef PLANCK_H
+#define PLANCK_H
+
+#include "matrix.h"
+#include "keymap_common.h"
+#include "backlight.h"
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include "i2cmaster.h"
+#include <util/delay.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);
+}
+
+#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 */                                       \
+   {                                                            \
+    { k00, k10, k20, k30, k40, KC_NO },   \
+    { k01, k11, k21, k31, k41, k51 },   \
+    { k02, k12, k22, k32, k42, k52 },   \
+    { k03, k13, k23, k33, k43, k53 },   \
+    { k04, k14, k24, k34, k44, k54 },   \
+    { k05, k15, k25, k35, KC_NO, k55 },   \
+    { k06, k16, KC_NO, k36, KC_NO, k56 },   \
+                                                                 \
+    { k07, k17, KC_NO, k37,KC_NO, k57 },   \
+    { k08, k18, k28, k38,KC_NO, k58 },   \
+    { k09, k19, k29, k39, k49, k59 },   \
+    { k0A, k1A, k2A, k3A, k4A, k5A },   \
+    { k0B, k1B, k2B, k3B, k4B, k5B },   \
+    { k0C, k1C, k2C, k3C, k4C, k5C },   \
+    { k0D, k1D, k2D, k3D, k4D, KC_NO }    \
+   }
+
+void * matrix_init_user(void);
+void * matrix_scan_user(void);
+
+
+
+#endif
\ No newline at end of file
diff --git a/keyboard/ergodox/i2cmaster.h b/keyboard/ergodox/i2cmaster.h
new file mode 100644 (file)
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/keymaps/keymap_default.c b/keyboard/ergodox/keymaps/keymap_default.c
new file mode 100644 (file)
index 0000000..7b54b48
--- /dev/null
@@ -0,0 +1,76 @@
+#include "ergodox.h"
+#include "debug.h"
+
+#define DEFAULT_LAYER 0
+#define COLEMAK_LAYER 1
+#define DVORAK_LAYER 2
+#define LOWER_LAYER 1
+#define RAISE_LAYER 4
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[DEFAULT_LAYER] = KEYMAP(  // layer 0 : default
+        // left hand
+        KC_EQL, KC_1,   KC_2,   KC_3,   KC_4,   KC_5,   KC_ESC,
+        KC_BSLS,KC_Q,   KC_W,   KC_E,   KC_R,   KC_T,   KC_FN2,
+        KC_TAB, KC_A,   KC_S,   KC_D,   KC_F,   KC_G,
+        KC_LSFT,KC_Z,   KC_X,   KC_C,   KC_V,   KC_B,   KC_FN1,
+        KC_LGUI,KC_GRV, KC_BSLS,KC_LEFT,KC_RGHT,
+                                      KC_LCTL,KC_LALT,
+                                           KC_HOME,
+                                 KC_BSPC,KC_DEL, KC_END,
+        // right hand
+             KC_FN3, KC_6,   KC_7,   KC_8,   KC_9,   KC_0,   KC_MINS,
+             KC_LBRC,KC_Y,   KC_U,   KC_I,   KC_O,   KC_P,   KC_RBRC,
+                  KC_H,   KC_J,   KC_K,   KC_L,   KC_SCLN,KC_QUOT,
+             KC_FN1, KC_N,   KC_M,   KC_COMM,KC_DOT, KC_SLSH,KC_RSFT,
+                       KC_LEFT,KC_DOWN,KC_UP,  KC_RGHT,KC_RGUI,
+        KC_RALT,KC_RCTL,
+        KC_PGUP,
+        KC_PGDN,KC_ENT, KC_SPC
+    ),
+[LOWER_LAYER] = KEYMAP(  // layer 0 : default
+        // left hand
+        KC_EQL, KC_1,   KC_2,   KC_3,   LALT(KC_TAB),   KC_5,   KC_ESC,
+        KC_BSLS,KC_Q,   S(KC_W),   KC_E,   KC_R,   KC_T,   KC_FN2,
+        KC_TAB, KC_A,   KC_S,   KC_D,   KC_F,   KC_G,
+        KC_LSFT,KC_Z,   KC_X,   KC_C,   KC_V,   KC_B,   KC_FN1,
+        KC_LGUI,KC_GRV, KC_BSLS,KC_LEFT,KC_RGHT,
+                                      KC_LCTL,KC_LALT,
+                                           KC_HOME,
+                                 KC_BSPC,KC_DEL, KC_END,
+        // right hand
+             KC_FN3, KC_6,   KC_7,   KC_8,   KC_9,   KC_0,   KC_MINS,
+             KC_LBRC,KC_Y,   KC_U,   KC_I,   KC_O,   KC_P,   KC_RBRC,
+             KC_H,   KC_J,   KC_K,   KC_L,   KC_SCLN,KC_QUOT,
+             KC_FN1, KC_N,   KC_M,   KC_COMM,KC_DOT, KC_SLSH,KC_RSFT,
+                       KC_LEFT,KC_DOWN,KC_UP,  KC_RGHT,KC_RGUI,
+        KC_RALT,KC_RCTL,
+        KC_PGUP,
+        KC_PGDN,KC_ENT, KC_SPC
+    )
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+    [1] = ACTION_LAYER_MOMENTARY(LOWER_LAYER),  // to RAISE
+    [2] = ACTION_LAYER_MOMENTARY(LOWER_LAYER),  // to LOWER
+
+    [3] = ACTION_DEFAULT_LAYER_SET(DEFAULT_LAYER),
+    [4] = ACTION_DEFAULT_LAYER_SET(COLEMAK_LAYER),
+    [5] = ACTION_DEFAULT_LAYER_SET(DVORAK_LAYER),
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+  // MACRODOWN only works in this function
+      switch(id) {
+        case 0:
+        if (record->event.pressed) {
+          register_code(KC_RSFT);
+        } else {
+          unregister_code(KC_RSFT);
+        }
+        break;
+      }
+    return MACRO_NONE;
+};
diff --git a/keyboard/ergodox/matrix.c b/keyboard/ergodox/matrix.c
new file mode 100644 (file)
index 0000000..cc10e29
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+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();
+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
+
+
+__attribute__ ((weak))
+void * matrix_init_kb(void) {
+};
+
+__attribute__ ((weak))
+void * matrix_scan_kb(void) {
+};
+
+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
+
+    mcp23018_status = init_mcp23018();
+    
+
+    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
+
+    if (matrix_init_kb) {
+        (*matrix_init_kb)();
+    }
+
+}
+
+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
+
+#ifdef KEYMAP_SIMON
+    uint8_t layer = biton32(layer_state);
+
+    ergodox_board_led_off();
+    switch (layer) {
+        case 0:
+// none
+            
+            break;
+        default:
+            ergodox_board_led_on();
+            break;
+    }
+#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];
+            }
+        }
+    }
+
+
+    if (matrix_scan_kb) {
+        (*matrix_scan_kb)();
+    }
+
+    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 100644 (file)
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 */
index cc3a1741a2333c00c055f901f6b7ae6363c8c09c..a4c711db823590b9e48e65fd17daf403db7b923d 100644 (file)
@@ -18,7 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef CONFIG_H
 #define CONFIG_H
 
-#include "config_definitions.h"
+#include "config_common.h"
 
 /* USB Device descriptor parameter */
 #define VENDOR_ID       0xFEED
@@ -58,73 +58,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
     keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
 )
 
-#ifdef BLUETOOTH_ENABLE
-#ifdef __AVR_ATmega32U4__
-    #define SERIAL_UART_BAUD       9600
-    #define SERIAL_UART_DATA       UDR1
-    #define SERIAL_UART_UBRR       ((F_CPU/(16UL*SERIAL_UART_BAUD))-1)
-    #define SERIAL_UART_RXD_VECT   USART1_RX_vect
-    #define SERIAL_UART_TXD_READY  (UCSR1A&(1<<UDRE1))
-    #define SERIAL_UART_INIT()     do { \
-        UBRR1L = (uint8_t) SERIAL_UART_UBRR;       /* baud rate */ \
-        UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8);  /* baud rate */ \
-        UCSR1B = (1<<TXEN1);                /* TX: enable */ \
-        UCSR1C = (0<<UPM11) | (0<<UPM10) | /* parity: none(00), even(01), odd(11) */ \
-                 (0<<UCSZ12) | (1<<UCSZ11) | (1<<UCSZ10); /* data-8bit(011) */ \
-               sei(); \
-    } while(0)
-#else
-#   error "USART configuration is needed."
-#endif
-
-
-// I'm fairly sure these aren't needed, but oh well - Jack
-
-/*
- * PS/2 Interrupt configuration
- */
-#ifdef PS2_USE_INT
-/* uses INT1 for clock line(ATMega32U4) */
-#define PS2_CLOCK_PORT  PORTD
-#define PS2_CLOCK_PIN   PIND
-#define PS2_CLOCK_DDR   DDRD
-#define PS2_CLOCK_BIT   1
-
-#define PS2_DATA_PORT   PORTD
-#define PS2_DATA_PIN    PIND
-#define PS2_DATA_DDR    DDRD
-#define PS2_DATA_BIT    0
-
-#define PS2_INT_INIT()  do {    \
-    EICRA |= ((1<<ISC11) |      \
-              (0<<ISC10));      \
-} while (0)
-#define PS2_INT_ON()  do {      \
-    EIMSK |= (1<<INT1);         \
-} while (0)
-#define PS2_INT_OFF() do {      \
-    EIMSK &= ~(1<<INT1);        \
-} while (0)
-#define PS2_INT_VECT    INT1_vect
-#endif
-
-/*
- * PS/2 Busywait configuration
- */
-#ifdef PS2_USE_BUSYWAIT
-#define PS2_CLOCK_PORT  PORTD
-#define PS2_CLOCK_PIN   PIND
-#define PS2_CLOCK_DDR   DDRD
-#define PS2_CLOCK_BIT   1
-
-#define PS2_DATA_PORT   PORTD
-#define PS2_DATA_PIN    PIND
-#define PS2_DATA_DDR    DDRD
-#define PS2_DATA_BIT    0
-#endif
-
-#endif
-
 /*
  * Feature disable options
  *  These options are also useful to firmware size reduction.
diff --git a/keyboard/planck/config_definitions.h b/keyboard/planck/config_definitions.h
deleted file mode 100644 (file)
index 2ac3112..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef CONFIG_DEFINITIONS_H
-#define CONFIG_DEFINITIONS_H
-
-#define B0 0x20
-#define B1 0x21
-#define B2 0x22
-#define B3 0x23
-#define B4 0x24
-#define B5 0x25
-#define B6 0x26
-#define B7 0x27
-#define C0 0x30
-#define C1 0x31
-#define C2 0x32
-#define C3 0x33
-#define C4 0x34
-#define C5 0x35
-#define C6 0x36
-#define C7 0x37
-#define D0 0x40
-#define D1 0x41
-#define D2 0x42
-#define D3 0x43
-#define D4 0x44
-#define D5 0x45
-#define D6 0x46
-#define D7 0x47
-#define E0 0x50
-#define E1 0x51
-#define E2 0x52
-#define E3 0x53
-#define E4 0x54
-#define E5 0x55
-#define E6 0x56
-#define E7 0x57
-#define F0 0x60
-#define F1 0x61
-#define F2 0x62
-#define F3 0x63
-#define F4 0x64
-#define F5 0x65
-#define F6 0x66
-#define F7 0x67
-
-#define COL2ROW 0x0
-#define ROW2COL 0x1
-
-
-
-#endif
-
index 9809a824cbb1611a2ef93df708191d8341c6c58e..b62862af04b8475ed3b67e3f29bff0f970a42dbf 100644 (file)
@@ -1,14 +1,16 @@
 #include "planck.h"
 
+__attribute__ ((weak))
 void * matrix_init_user(void) {
 
 };
 
+__attribute__ ((weak))
 void * matrix_scan_user(void) {
 
 };
 
-void *matrix_init_kb(void) {
+void * matrix_init_kb(void) {
        #ifdef BACKLIGHT_ENABLE
        backlight_init_ports();
        #endif
@@ -22,7 +24,7 @@ void *matrix_init_kb(void) {
        }
 };
 
-void *matrix_scan_kb(void) {
+void * matrix_scan_kb(void) {
        if (matrix_scan_user) {
                (*matrix_scan_user)();
        }
index 1637284047a18c0a567ea19d373eefdcd717a7e7..c68bce8ff0c4f3181dc0aef0b50c85d5916d70a0 100644 (file)
@@ -42,9 +42,12 @@ QUANTUM_DIR = $(TOP_DIR)/quantum
 
 # # project specific files
 SRC += $(QUANTUM_DIR)/keymap_common.c \
-       $(QUANTUM_DIR)/matrix.c \
        $(QUANTUM_DIR)/led.c 
 
+ifndef CUSTOM_MATRIX
+       SRC += $(QUANTUM_DIR)/matrix.c
+endif
+
 ifdef MIDI_ENABLE
        SRC += $(QUANTUM_DIR)/keymap_midi.c \
                   $(QUANTUM_DIR)/beeps.c
@@ -58,8 +61,6 @@ endif
 #EXTRALDFLAGS = -Wl,--relax
 
 # Search Path
-VPATH += $(TARGET_DIR)
-VPATH += $(TOP_DIR)
 VPATH += $(QUANTUM_DIR)
 
 include $(TOP_DIR)/protocol/lufa.mk
diff --git a/quantum/config_common.h b/quantum/config_common.h
new file mode 100644 (file)
index 0000000..da53fce
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef CONFIG_DEFINITIONS_H
+#define CONFIG_DEFINITIONS_H
+
+#define B0 0x20
+#define B1 0x21
+#define B2 0x22
+#define B3 0x23
+#define B4 0x24
+#define B5 0x25
+#define B6 0x26
+#define B7 0x27
+#define C0 0x30
+#define C1 0x31
+#define C2 0x32
+#define C3 0x33
+#define C4 0x34
+#define C5 0x35
+#define C6 0x36
+#define C7 0x37
+#define D0 0x40
+#define D1 0x41
+#define D2 0x42
+#define D3 0x43
+#define D4 0x44
+#define D5 0x45
+#define D6 0x46
+#define D7 0x47
+#define E0 0x50
+#define E1 0x51
+#define E2 0x52
+#define E3 0x53
+#define E4 0x54
+#define E5 0x55
+#define E6 0x56
+#define E7 0x57
+#define F0 0x60
+#define F1 0x61
+#define F2 0x62
+#define F3 0x63
+#define F4 0x64
+#define F5 0x65
+#define F6 0x66
+#define F7 0x67
+
+#define COL2ROW 0x0
+#define ROW2COL 0x1
+
+#ifdef BLUETOOTH_ENABLE
+#ifdef __AVR_ATmega32U4__
+    #define SERIAL_UART_BAUD       9600
+    #define SERIAL_UART_DATA       UDR1
+    #define SERIAL_UART_UBRR       ((F_CPU/(16UL*SERIAL_UART_BAUD))-1)
+    #define SERIAL_UART_RXD_VECT   USART1_RX_vect
+    #define SERIAL_UART_TXD_READY  (UCSR1A&(1<<UDRE1))
+    #define SERIAL_UART_INIT()     do { \
+        UBRR1L = (uint8_t) SERIAL_UART_UBRR;       /* baud rate */ \
+        UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8);  /* baud rate */ \
+        UCSR1B = (1<<TXEN1);                /* TX: enable */ \
+        UCSR1C = (0<<UPM11) | (0<<UPM10) | /* parity: none(00), even(01), odd(11) */ \
+                 (0<<UCSZ12) | (1<<UCSZ11) | (1<<UCSZ10); /* data-8bit(011) */ \
+               sei(); \
+    } while(0)
+#else
+#   error "USART configuration is needed."
+#endif
+
+
+// I'm fairly sure these aren't needed, but oh well - Jack
+
+/*
+ * PS/2 Interrupt configuration
+ */
+#ifdef PS2_USE_INT
+/* uses INT1 for clock line(ATMega32U4) */
+#define PS2_CLOCK_PORT  PORTD
+#define PS2_CLOCK_PIN   PIND
+#define PS2_CLOCK_DDR   DDRD
+#define PS2_CLOCK_BIT   1
+
+#define PS2_DATA_PORT   PORTD
+#define PS2_DATA_PIN    PIND
+#define PS2_DATA_DDR    DDRD
+#define PS2_DATA_BIT    0
+
+#define PS2_INT_INIT()  do {    \
+    EICRA |= ((1<<ISC11) |      \
+              (0<<ISC10));      \
+} while (0)
+#define PS2_INT_ON()  do {      \
+    EIMSK |= (1<<INT1);         \
+} while (0)
+#define PS2_INT_OFF() do {      \
+    EIMSK &= ~(1<<INT1);        \
+} while (0)
+#define PS2_INT_VECT    INT1_vect
+#endif
+
+/*
+ * PS/2 Busywait configuration
+ */
+#ifdef PS2_USE_BUSYWAIT
+#define PS2_CLOCK_PORT  PORTD
+#define PS2_CLOCK_PIN   PIND
+#define PS2_CLOCK_DDR   DDRD
+#define PS2_CLOCK_BIT   1
+
+#define PS2_DATA_PORT   PORTD
+#define PS2_DATA_PIN    PIND
+#define PS2_DATA_DDR    DDRD
+#define PS2_DATA_BIT    0
+#endif
+
+#endif
+
+#endif
+
index 66cf2883c7cca9b247190038124b5f8047b796c7..c9e1494fd9d636dd3c459b616f79c98ead1acef3 100644 (file)
@@ -37,15 +37,18 @@ action_t action_for_key(uint8_t layer, keypos_t key)
        // Has a modifier
        action_t action;
        // Split it up
-       action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF);
+       action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
        return action;
        } else if (keycode >= 0x2000 && keycode < 0x3000) {
-               // Is a shortcut for function layer, pull last 12bits
+        // Is a shortcut for function layer, pull last 12bits
+        // This means we have 4,096 FN macros at our disposal
         return keymap_func_to_action(keycode & 0xFFF);
        } else if (keycode >= 0x3000 && keycode < 0x4000) {
+      // When the code starts with 3, it's an action macro.
        action_t action;
        action.code = ACTION_MACRO(keycode & 0xFF);
        return action;
+#ifdef BACKLIGHT_ENABLE
        } else if (keycode >= BL_0 & keycode <= BL_15) {
         action_t action;
         action.code = ACTION_BACKLIGHT_LEVEL(keycode & 0x000F);
@@ -66,10 +69,12 @@ action_t action_for_key(uint8_t layer, keypos_t key)
         action_t action;
         action.code = ACTION_BACKLIGHT_STEP();
         return action;
-    } else if (keycode == RESET) {
+#endif
+    } else if (keycode == RESET) { // RESET is 0x5000, which is why this is here
         bootloader_jump();
         return;
-    } else if (keycode == DEBUG) {
+    } else if (keycode == DEBUG) { // DEBUG is 0x5001
+      // TODO: Does this actually work?
         print("\nDEBUG: enabled.\n");
         debug_enable = true;
         return;
@@ -79,15 +84,21 @@ action_t action_for_key(uint8_t layer, keypos_t key)
         action_t action;
         action.code = ACTION_LAYER_SET(layer, when);
         return action;
+#ifdef MIDI_ENABLE
     } else if (keycode >= 0x6000 && keycode < 0x7000) {
         action_t action;
         action.code =  ACTION_FUNCTION_OPT(keycode & 0xFF, (keycode & 0x0F00) >> 8);
         return action;
+#endif
+#ifdef UNICODE_ENABLE
     } else if (keycode >= 0x8000) {
         action_t action;
         uint16_t unicode = keycode & ~(0x8000);
         action.code =  ACTION_FUNCTION_OPT(unicode & 0xFF, (unicode & 0xFF00) >> 8);
         return action;
+#endif
+    } else {
+
     }
 
     switch (keycode) {
index 97642a4a4e1a7a98e829bb9d597a1d31a4078202..95bf4c0973b3f0cfe205f52104e20cedb0c4b150 100644 (file)
@@ -47,6 +47,16 @@ static void init_cols(void);
 static void unselect_rows(void);
 static void select_row(uint8_t row);
 
+__attribute__ ((weak))
+void * matrix_init_kb(void) {
+
+};
+
+__attribute__ ((weak))
+void * matrix_scan_kb(void) {
+
+};
+
 inline
 uint8_t matrix_rows(void)
 {