summary refs log tree commit diff
path: root/quantum
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2015-10-26 14:49:46 -0400
committerJack Humbert <jack.humb@gmail.com>2015-10-26 14:49:46 -0400
commit46e7fb2d3ccd699c0a1b1fd9d02860b1f2a44141 (patch)
treef0b00f664ecdaf83e30f27baf20780eb5d91c39a /quantum
parentff8d8a50dfbb8502003a5181878c54a71b8c57d5 (diff)
quantum separated
Diffstat (limited to 'quantum')
-rw-r--r--quantum/analog.c53
-rw-r--r--quantum/analog.h36
-rw-r--r--quantum/beeps.c246
-rw-r--r--quantum/beeps.h12
-rw-r--r--quantum/keymap_common.c226
-rw-r--r--quantum/keymap_common.h121
-rw-r--r--quantum/keymap_extras/keymap_colemak.h74
-rw-r--r--quantum/keymap_extras/keymap_dvorak.h72
-rw-r--r--quantum/keymap_extras/keymap_french.h83
-rw-r--r--quantum/keymap_extras/keymap_nordic.h59
-rw-r--r--quantum/keymap_extras/keymap_spanish.h62
-rw-r--r--quantum/keymap_extras/keymap_uk.h36
-rw-r--r--quantum/keymap_midi.c110
-rw-r--r--quantum/keymap_midi.h220
-rw-r--r--quantum/keymap_unicode.c59
-rw-r--r--quantum/led.c38
-rw-r--r--quantum/matrix.c301
17 files changed, 1808 insertions, 0 deletions
diff --git a/quantum/analog.c b/quantum/analog.c
new file mode 100644
index 0000000000..49b84ee0e8
--- /dev/null
+++ b/quantum/analog.c
@@ -0,0 +1,53 @@
+// Simple analog to digitial conversion
+
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <stdint.h>
+#include "analog.h"
+
+
+static uint8_t aref = (1<<REFS0); // default to AREF = Vcc
+
+
+void analogReference(uint8_t mode)
+{
+	aref = mode & 0xC0;
+}
+
+
+// Arduino compatible pin input
+int16_t analogRead(uint8_t pin)
+{
+#if defined(__AVR_ATmega32U4__)
+	static const uint8_t PROGMEM pin_to_mux[] = {
+		0x00, 0x01, 0x04, 0x05, 0x06, 0x07,
+		0x25, 0x24, 0x23, 0x22, 0x21, 0x20};
+	if (pin >= 12) return 0;
+	return adc_read(pgm_read_byte(pin_to_mux + pin));
+#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+	if (pin >= 8) return 0;
+	return adc_read(pin);
+#else
+	return 0;
+#endif
+}
+
+// Mux input
+int16_t adc_read(uint8_t mux)
+{
+#if defined(__AVR_AT90USB162__)
+	return 0;
+#else
+	uint8_t low;
+
+	ADCSRA = (1<<ADEN) | ADC_PRESCALER;		// enable ADC
+	ADCSRB = (1<<ADHSM) | (mux & 0x20);		// high speed mode
+	ADMUX = aref | (mux & 0x1F);			// configure mux input
+	ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC);	// start the conversion
+	while (ADCSRA & (1<<ADSC)) ;			// wait for result
+	low = ADCL;					// must read LSB first
+	return (ADCH << 8) | low;			// must read MSB only once!
+#endif
+}
+
+
diff --git a/quantum/analog.h b/quantum/analog.h
new file mode 100644
index 0000000000..9b95a93bef
--- /dev/null
+++ b/quantum/analog.h
@@ -0,0 +1,36 @@
+#ifndef _analog_h_included__
+#define _analog_h_included__
+
+#include <stdint.h>
+
+void analogReference(uint8_t mode);
+int16_t analogRead(uint8_t pin);
+int16_t adc_read(uint8_t mux);
+
+#define ADC_REF_POWER     (1<<REFS0)
+#define ADC_REF_INTERNAL  ((1<<REFS1) | (1<<REFS0))
+#define ADC_REF_EXTERNAL  (0)
+
+// These prescaler values are for high speed mode, ADHSM = 1
+#if F_CPU == 16000000L
+#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS1))
+#elif F_CPU == 8000000L
+#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS0))
+#elif F_CPU == 4000000L
+#define ADC_PRESCALER ((1<<ADPS2))
+#elif F_CPU == 2000000L
+#define ADC_PRESCALER ((1<<ADPS1) | (1<<ADPS0))
+#elif F_CPU == 1000000L
+#define ADC_PRESCALER ((1<<ADPS1))
+#else
+#define ADC_PRESCALER ((1<<ADPS0))
+#endif
+
+// some avr-libc versions do not properly define ADHSM
+#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+#if !defined(ADHSM)
+#define ADHSM (7)
+#endif
+#endif
+
+#endif
diff --git a/quantum/beeps.c b/quantum/beeps.c
new file mode 100644
index 0000000000..8d1f81f210
--- /dev/null
+++ b/quantum/beeps.c
@@ -0,0 +1,246 @@
+#include "beeps.h"
+#include <math.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+
+#define PI 3.14159265
+
+void delay_us(int count) {
+  while(count--) {
+    _delay_us(1);
+  }
+}
+
+int voices = 0;
+double frequency = 0;
+int volume = 0;
+int position = 0;
+
+double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+bool sliding = false;
+#define RANGE 1000
+volatile int i=0; //elements of the wave
+
+
+void beeps() {
+    play_notes();
+}
+
+void send_freq(double freq, int vol) {
+    int duty = (((double)F_CPU) / freq);
+    ICR3 = duty; // Set max to the period
+    OCR3A = duty >> (0x10 - vol); // Set compare to half the period
+}
+
+void stop_all_notes() {
+    voices = 0;
+    TCCR3A = 0;
+    TCCR3B = 0;
+    frequency = 0;
+    volume = 0;
+
+    for (int i = 0; i < 8; i++) {
+        frequencies[i] = 0;
+        volumes[i] = 0;
+    }
+}
+
+void stop_note(double freq) {
+    for (int i = 7; i >= 0; i--) {
+        if (frequencies[i] == freq) {
+            frequencies[i] = 0;
+            volumes[i] = 0;
+            for (int j = i; (j < 7); j++) {
+                frequencies[j] = frequencies[j+1];
+                frequencies[j+1] = 0;
+                volumes[j] = volumes[j+1];
+                volumes[j+1] = 0;
+            }
+        }
+    }
+    voices--;
+    if (voices < 0)
+        voices = 0;
+    if (voices == 0) {
+        TCCR3A = 0;
+        TCCR3B = 0;
+        frequency = 0;
+        volume = 0;
+    } else {
+        double freq = frequencies[voices - 1];
+        int vol = volumes[voices - 1];
+        if (frequency < freq) {
+            sliding = true;
+            for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) {
+                send_freq(f, vol);
+            }
+            sliding = false;
+        } else if (frequency > freq) {
+            sliding = true;
+            for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) {
+                send_freq(f, vol);
+            }
+            sliding = false;
+        }
+        send_freq(freq, vol);
+        frequency = freq;
+        volume = vol;
+    }
+}
+
+void init_notes() {
+    // TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (1 << WGM10);
+    // TCCR1B = (1 << COM1B1) | (0 << COM1A0) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10);
+
+    // DDRC |= (1<<6); 
+
+    // TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
+    // TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (0 << CS31) | (1 << CS30);
+
+    // ICR3 = 0xFFFF; 
+    // OCR3A = (int)((float)wave[i]*ICR3/RANGE); //go to next array element
+
+
+    // cli();
+
+    // /* Enable interrupt on timer2 == 127, with clk/8 prescaler. At 16MHz,
+    //    this gives a timer interrupt at 15625Hz. */
+    // TIMSK3 = (1 << OCIE3A);
+
+    // /* clear/reset timer on match */
+    // // TCCR3A = 1<<WGM31 | 0<<WGM30;  CTC mode, reset on match 
+    // // TCCR3B = 0<<CS32 | 1<<CS31 | 0<<CS30; /* clk, /8 prescaler */
+
+    // TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
+    // TCCR3B = (0 << WGM33) | (0 << WGM32) | (0 << CS32) | (0 << CS31) | (1 << CS30);
+
+
+    // TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
+    // TCCR1B = (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10);
+    // // SPCR = 0x50;
+    // // SPSR = 0x01;
+    // DDRC |= (1<<6);
+    // // ICR3 = 0xFFFF; 
+    // // OCR3A=80;
+    // PORTC |= (1<<6);
+
+    // sei();
+}
+
+// #define highByte(c) ((c >> 8) & 0x00FF)
+// #define lowByte(c) (c & 0x00FF)
+
+ISR(TIMER3_COMPA_vect) {
+
+    if (ICR3 > 0 && !sliding) {
+        switch (position) {
+            case 0: {
+                int duty = (((double)F_CPU) / (frequency));
+                ICR3 = duty; // Set max to the period
+                OCR3A = duty >> 1; // Set compare to half the period
+                break;
+            }
+            case 1: {
+                int duty = (((double)F_CPU) / (frequency*2));
+                ICR3 = duty; // Set max to the period
+                OCR3A = duty >> 1; // Set compare to half the period
+                break;
+            }
+            case 2: {
+                int duty = (((double)F_CPU) / (frequency*3));
+                ICR3 = duty; // Set max to the period
+                OCR3A = duty >> 1; // Set compare to half the period
+                break;
+            }
+        }
+        position = (position + 1) % 3;
+    }
+//     /* OCR2A has been cleared, per TCCR2A above */
+//     // OCR3A = 127;
+
+//     // pos1 += incr1;
+//     // pos2 += incr2;
+//     // pos3 += incr3;
+
+//     // sample = sinewave[highByte(pos1)] + sinewave[highByte(pos2)] + sinewave[highByte(pos3)];
+
+//     // OCR3A = sample;
+
+
+//     OCR3A=pgm_read_byte(&sinewave[pos1]);
+//     pos1++;
+//     // PORTC &= ~(1<<6);
+
+//     /* buffered, 1x gain, active mode */
+//     // SPDR = highByte(sample) | 0x70;
+//     // while (!(SPSR & (1<<SPIF)));
+
+//     // SPDR = lowByte(sample);
+//     // while (!(SPSR & (1<<SPIF)));
+
+//     // PORTC |= (1<<6);
+}
+
+void play_note(double freq, int vol) {
+
+    if (freq > 0) {
+        DDRC |= (1<<6); 
+
+        TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
+        TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
+
+        if (frequency != 0) {
+            if (frequency < freq) {
+                for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) {
+                    send_freq(f, vol);
+                }
+            } else if (frequency > freq) {
+                for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) {
+                    send_freq(f, vol);
+                }
+            }
+        }
+        send_freq(freq, vol);
+        frequency = freq;
+        volume = vol;
+
+        frequencies[voices] = frequency;
+        volumes[voices] = volume;
+        voices++;
+    }
+    // ICR3 = 0xFFFF;
+    // for (int i = 0; i < 10000; i++) {
+    //     OCR3A = round((sin(i*freq)*.5)+.5)*0xFFFF;
+    //     // _delay_us(50);
+    // }
+
+    // TCCR3A = 0;
+    // TCCR3B = 0;
+}
+
+// void note(int x, float length) {
+//     DDRC |= (1<<6);
+// 	int t = (int)(440*pow(2,-x/12.0)); // starting note
+//     for (int y = 0; y < length*1000/t; y++) { // note length
+//         PORTC |= (1<<6);
+//         delay_us(t);
+//         PORTC &= ~(1<<6);
+//         delay_us(t);
+//     }
+// 	PORTC &= ~(1<<6);
+// }
+
+// void true_note(float x, float y, float length) {
+// 	for (uint32_t i = 0; i < length * 50; i++) {
+// 		uint32_t v = (uint32_t) (round(sin(PI*2*i*640000*pow(2, x/12.0))*.5+1 + sin(PI*2*i*640000*pow(2, y/12.0))*.5+1) / 2 * pow(2, 8)); 
+// 		for (int u = 0; u < 8; u++) {
+// 			if (v & (1 << u) && !(PORTC&(1<<6)))
+// 		        PORTC |= (1<<6);
+// 		    else if (PORTC&(1<<6))
+// 	        	PORTC &= ~(1<<6);
+// 		}
+// 	}
+// 	PORTC &= ~(1<<6);
+// }
\ No newline at end of file
diff --git a/quantum/beeps.h b/quantum/beeps.h
new file mode 100644
index 0000000000..378983c605
--- /dev/null
+++ b/quantum/beeps.h
@@ -0,0 +1,12 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+void note(int x, float length);
+void beeps();
+void true_note(float x, float y, float length);
+void play_note(double freq, int vol);
+void stop_note(double freq);
+void stop_all_notes();
+void init_notes();
\ No newline at end of file
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
new file mode 100644
index 0000000000..66cf2883c7
--- /dev/null
+++ b/quantum/keymap_common.c
@@ -0,0 +1,226 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "keymap_common.h"
+#include "report.h"
+#include "keycode.h"
+#include "action_layer.h"
+#include "action.h"
+#include "action_macro.h"
+#include "debug.h"
+#include "backlight.h"
+#include "keymap_midi.h"
+
+static action_t keycode_to_action(uint16_t keycode);
+
+/* converts key to action */
+action_t action_for_key(uint8_t layer, keypos_t key)
+{
+	// 16bit keycodes - important
+    uint16_t keycode = keymap_key_to_keycode(layer, key);
+
+    if (keycode >= 0x0100 && keycode < 0x2000) {
+    	// Has a modifier
+    	action_t action;
+    	// Split it up
+    	action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF);
+    	return action;
+	} else if (keycode >= 0x2000 && keycode < 0x3000) {
+		// Is a shortcut for function layer, pull last 12bits
+        return keymap_func_to_action(keycode & 0xFFF);
+	} else if (keycode >= 0x3000 && keycode < 0x4000) {
+    	action_t action;
+    	action.code = ACTION_MACRO(keycode & 0xFF);
+    	return action;
+	} else if (keycode >= BL_0 & keycode <= BL_15) {
+        action_t action;
+        action.code = ACTION_BACKLIGHT_LEVEL(keycode & 0x000F);
+        return action;
+    } else if (keycode == BL_DEC) {
+        action_t action;
+        action.code = ACTION_BACKLIGHT_DECREASE();
+        return action;
+    } else if (keycode == BL_INC) {
+        action_t action;
+        action.code = ACTION_BACKLIGHT_INCREASE();
+        return action;
+    } else if (keycode == BL_TOGG) {
+        action_t action;
+        action.code = ACTION_BACKLIGHT_TOGGLE();
+        return action;
+    } else if (keycode == BL_STEP) {
+        action_t action;
+        action.code = ACTION_BACKLIGHT_STEP();
+        return action;
+    } else if (keycode == RESET) {
+        bootloader_jump();
+        return;
+    } else if (keycode == DEBUG) {
+        print("\nDEBUG: enabled.\n");
+        debug_enable = true;
+        return;
+    } else if (keycode >= 0x5000 && keycode < 0x6000) {
+        int when = (keycode >> 0x9) & 0x3;
+        int layer = keycode & 0xFF;
+        action_t action;
+        action.code = ACTION_LAYER_SET(layer, when);
+        return action;
+    } else if (keycode >= 0x6000 && keycode < 0x7000) {
+        action_t action;
+        action.code =  ACTION_FUNCTION_OPT(keycode & 0xFF, (keycode & 0x0F00) >> 8);
+        return action;
+    } else if (keycode >= 0x8000) {
+        action_t action;
+        uint16_t unicode = keycode & ~(0x8000);
+        action.code =  ACTION_FUNCTION_OPT(unicode & 0xFF, (unicode & 0xFF00) >> 8);
+        return action;
+    }
+
+    switch (keycode) {
+        case KC_FN0 ... KC_FN31:
+            return keymap_fn_to_action(keycode);
+#ifdef BOOTMAGIC_ENABLE
+        case KC_CAPSLOCK:
+        case KC_LOCKING_CAPS:
+            if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
+                return keycode_to_action(KC_LCTL);
+            }
+            return keycode_to_action(keycode);
+        case KC_LCTL:
+            if (keymap_config.swap_control_capslock) {
+                return keycode_to_action(KC_CAPSLOCK);
+            }
+            return keycode_to_action(KC_LCTL);
+        case KC_LALT:
+            if (keymap_config.swap_lalt_lgui) {
+                if (keymap_config.no_gui) {
+                    return keycode_to_action(ACTION_NO);
+                }
+                return keycode_to_action(KC_LGUI);
+            }
+            return keycode_to_action(KC_LALT);
+        case KC_LGUI:
+            if (keymap_config.swap_lalt_lgui) {
+                return keycode_to_action(KC_LALT);
+            }
+            if (keymap_config.no_gui) {
+                return keycode_to_action(ACTION_NO);
+            }
+            return keycode_to_action(KC_LGUI);
+        case KC_RALT:
+            if (keymap_config.swap_ralt_rgui) {
+                if (keymap_config.no_gui) {
+                    return keycode_to_action(ACTION_NO);
+                }
+                return keycode_to_action(KC_RGUI);
+            }
+            return keycode_to_action(KC_RALT);
+        case KC_RGUI:
+            if (keymap_config.swap_ralt_rgui) {
+                return keycode_to_action(KC_RALT);
+            }
+            if (keymap_config.no_gui) {
+                return keycode_to_action(ACTION_NO);
+            }
+            return keycode_to_action(KC_RGUI);
+        case KC_GRAVE:
+            if (keymap_config.swap_grave_esc) {
+                return keycode_to_action(KC_ESC);
+            }
+            return keycode_to_action(KC_GRAVE);
+        case KC_ESC:
+            if (keymap_config.swap_grave_esc) {
+                return keycode_to_action(KC_GRAVE);
+            }
+            return keycode_to_action(KC_ESC);
+        case KC_BSLASH:
+            if (keymap_config.swap_backslash_backspace) {
+                return keycode_to_action(KC_BSPACE);
+            }
+            return keycode_to_action(KC_BSLASH);
+        case KC_BSPACE:
+            if (keymap_config.swap_backslash_backspace) {
+                return keycode_to_action(KC_BSLASH);
+            }
+            return keycode_to_action(KC_BSPACE);
+#endif
+        default:
+            return keycode_to_action(keycode);
+    }
+}
+
+
+/* Macro */
+__attribute__ ((weak))
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+    return MACRO_NONE;
+}
+
+/* Function */
+__attribute__ ((weak))
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+}
+
+/* translates keycode to action */
+static action_t keycode_to_action(uint16_t keycode)
+{
+    action_t action;
+    switch (keycode) {
+        case KC_A ... KC_EXSEL:
+        case KC_LCTRL ... KC_RGUI:
+            action.code = ACTION_KEY(keycode);
+            break;
+        case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
+            action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
+            break;
+        case KC_AUDIO_MUTE ... KC_WWW_FAVORITES:
+            action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
+            break;
+        case KC_MS_UP ... KC_MS_ACCEL2:
+            action.code = ACTION_MOUSEKEY(keycode);
+            break;
+        case KC_TRNS:
+            action.code = ACTION_TRANSPARENT;
+            break;
+        default:
+            action.code = ACTION_NO;
+            break;
+    }
+    return action;
+}
+
+
+/* translates key to keycode */
+uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
+{
+	// Read entire word (16bits)
+    return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]);
+}
+
+/* translates Fn keycode to action */
+action_t keymap_fn_to_action(uint16_t keycode)
+{
+    return (action_t){ .code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]) };
+}
+
+action_t keymap_func_to_action(uint16_t keycode)
+{
+	// For FUNC without 8bit limit
+    return (action_t){ .code = pgm_read_word(&fn_actions[(int)keycode]) };
+}
diff --git a/quantum/keymap_common.h b/quantum/keymap_common.h
new file mode 100644
index 0000000000..091f7d8f3e
--- /dev/null
+++ b/quantum/keymap_common.h
@@ -0,0 +1,121 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEYMAP_H
+#define KEYMAP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "action.h"
+#include <avr/pgmspace.h>
+#include "keycode.h"
+#include "keymap.h"
+#include "action_macro.h"
+#include "report.h"
+#include "host.h"
+// #include "print.h"
+#include "debug.h"
+
+#ifdef BOOTMAGIC_ENABLE
+/* NOTE: Not portable. Bit field order depends on implementation */
+typedef union {
+    uint16_t raw;
+    struct {
+        bool swap_control_capslock:1;
+        bool capslock_to_control:1;
+        bool swap_lalt_lgui:1;
+        bool swap_ralt_rgui:1;
+        bool no_gui:1;
+        bool swap_grave_esc:1;
+        bool swap_backslash_backspace:1;
+        bool nkro:1;
+    };
+} keymap_config_t;
+keymap_config_t keymap_config;
+#endif
+
+
+/* translates key to keycode */
+uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
+
+/* translates Fn keycode to action */
+action_t keymap_fn_to_action(uint16_t keycode);
+
+/* translates Fn keycode to action */
+action_t keymap_func_to_action(uint16_t keycode);
+
+extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
+extern const uint16_t fn_actions[];
+
+// Ability to use mods in layouts
+#define LCTL(kc) kc | 0x0100
+#define LSFT(kc) kc | 0x0200
+#define LALT(kc) kc | 0x0400
+#define LGUI(kc) kc | 0x0800
+#define RCTL(kc) kc | 0x1100
+#define RSFT(kc) kc | 0x1200
+#define RALT(kc) kc | 0x1400
+#define RGUI(kc) kc | 0x1800
+
+// Alias for function layers than expand past FN31
+#define FUNC(kc) kc | 0x2000
+
+// Aliases
+#define S(kc) LSFT(kc)
+#define F(kc) FUNC(kc)
+
+#define M(kc) kc | 0x3000
+
+#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
+
+#define BL_ON 0x4009
+#define BL_OFF 0x4000
+#define BL_0 0x4000
+#define BL_1 0x4001
+#define BL_2 0x4002
+#define BL_3 0x4003
+#define BL_4 0x4004
+#define BL_5 0x4005
+#define BL_6 0x4006
+#define BL_7 0x4007
+#define BL_8 0x4008
+#define BL_9 0x4009
+#define BL_10 0x400A
+#define BL_11 0x400B
+#define BL_12 0x400C
+#define BL_13 0x400D
+#define BL_14 0x400E
+#define BL_15 0x400F
+#define BL_DEC 0x4010
+#define BL_INC 0x4011
+#define BL_TOGG 0x4012
+#define BL_STEP 0x4013
+
+#define RESET 0x5000
+#define DEBUG 0x5001
+
+// ON_PRESS    = 1
+// ON_RELEASE  = 2
+// ON_BOTH     = 3
+#define TO(layer, when) (layer | 0x5100 | (when << 0x9))
+
+#define MIDI(n) (n | 0x6000)
+
+#define UNI(n) (n | 0x8000)
+
+
+#endif
diff --git a/quantum/keymap_extras/keymap_colemak.h b/quantum/keymap_extras/keymap_colemak.h
new file mode 100644
index 0000000000..c8066ea666
--- /dev/null
+++ b/quantum/keymap_extras/keymap_colemak.h
@@ -0,0 +1,74 @@
+#ifndef KEYMAP_COLEMAK_H
+#define KEYMAP_COLEMAK_H
+
+#include "keymap_common.h"
+// For software implementation of colemak
+#define CM_Q    KC_Q
+#define CM_W    KC_W
+#define CM_F    KC_E
+#define CM_P    KC_R
+#define CM_G    KC_T
+#define CM_J    KC_Y
+#define CM_L    KC_U
+#define CM_U    KC_I
+#define CM_Y    KC_O
+#define CM_SCLN KC_P
+
+#define CM_A    KC_A
+#define CM_R    KC_S
+#define CM_S    KC_D
+#define CM_T    KC_F
+#define CM_D    KC_G
+#define CM_H    KC_H
+#define CM_N    KC_J
+#define CM_E    KC_K
+#define CM_I    KC_L
+#define CM_O    KC_SCLN
+
+#define CM_Z    KC_Z
+#define CM_X    KC_X
+#define CM_C    KC_C
+#define CM_V    KC_V
+#define CM_B    KC_B
+#define CM_K    KC_N
+#define CM_M    KC_M
+#define CM_COMM KC_COMM
+#define CM_DOT  KC_DOT
+#define CM_SLSH KC_SLSH
+
+// Make it easy to support these in macros
+// TODO: change macro implementation so these aren't needed
+#define KC_CM_Q    CM_Q    
+#define KC_CM_W    CM_W    
+#define KC_CM_F    CM_F    
+#define KC_CM_P    CM_P    
+#define KC_CM_G    CM_G    
+#define KC_CM_J    CM_J    
+#define KC_CM_L    CM_L    
+#define KC_CM_U    CM_U    
+#define KC_CM_Y    CM_Y    
+#define KC_CM_SCLN CM_SCLN 
+
+#define KC_CM_A    CM_A    
+#define KC_CM_R    CM_R    
+#define KC_CM_S    CM_S    
+#define KC_CM_T    CM_T    
+#define KC_CM_D    CM_D    
+#define KC_CM_H    CM_H    
+#define KC_CM_N    CM_N    
+#define KC_CM_E    CM_E    
+#define KC_CM_I    CM_I    
+#define KC_CM_O    CM_O    
+
+#define KC_CM_Z    CM_Z    
+#define KC_CM_X    CM_X    
+#define KC_CM_C    CM_C    
+#define KC_CM_V    CM_V    
+#define KC_CM_B    CM_B    
+#define KC_CM_K    CM_K    
+#define KC_CM_M    CM_M    
+#define KC_CM_COMM CM_COMM 
+#define KC_CM_DOT  CM_DOT  
+#define KC_CM_SLSH CM_SLSH 
+
+#endif
diff --git a/quantum/keymap_extras/keymap_dvorak.h b/quantum/keymap_extras/keymap_dvorak.h
new file mode 100644
index 0000000000..d172e0019b
--- /dev/null
+++ b/quantum/keymap_extras/keymap_dvorak.h
@@ -0,0 +1,72 @@
+#ifndef KEYMAP_DVORAK_H
+#define KEYMAP_DVORAK_H
+
+#include "keymap_common.h"
+
+// Normal characters
+#define DV_GRV	KC_GRV
+#define DV_1	KC_1
+#define DV_2	KC_2
+#define DV_3	KC_3
+#define DV_4	KC_4
+#define DV_5	KC_5
+#define DV_6	KC_6
+#define DV_7	KC_7
+#define DV_8	KC_8
+#define DV_9	KC_9
+#define DV_0	KC_0
+#define DV_LBRC	KC_MINS
+#define DV_RBRC	KC_EQL
+
+#define DV_QUOT KC_Q
+#define DV_COMM	KC_W
+#define DV_DOT	KC_E
+#define DV_P	KC_R
+#define DV_Y	KC_T
+#define	DV_F	KC_Y
+#define DV_G	KC_U
+#define DV_C 	KC_I
+#define	DV_R	KC_O
+#define DV_L	KC_P
+#define DV_SLSH	KC_LBRC
+#define DV_EQL	KC_RBRC
+
+#define DV_A	KC_A
+#define DV_O	KC_S
+#define DV_E	KC_D
+#define DV_U	KC_F
+#define DV_I	KC_G
+#define DV_D	KC_H
+#define DV_H	KC_J
+#define DV_T	KC_K
+#define DV_N	KC_L
+#define DV_S	KC_SCLN
+#define DV_MINS	KC_QUOT
+
+#define DV_SCLN	KC_Z
+#define DV_Q	KC_X
+#define DV_J	KC_C
+#define DV_K	KC_V
+#define DV_X	KC_B
+#define DV_B	KC_N
+#define DV_M	KC_M
+#define DV_W	KC_COMM
+#define DV_V	KC_DOT
+#define DV_Z	KC_SLSH
+
+// Shifted characters
+#define DV_TILD	LSFT(DV_GRV)
+#define DV_EXLM	LSFT(DV_1)
+#define DV_AT	LSFT(DV_2)
+#define DV_HASH	LSFT(DV_3)
+#define DV_DLR	LSFT(DV_4)
+#define DV_PERC	LSFT(DV_5)
+#define DV_CIRC	LSFT(DV_6)
+#define DV_AMPR	LSFT(DV_7)
+#define DV_ASTR	LSFT(DV_8)
+#define DV_LPRN	LSFT(DV_9)
+#define DV_RPRN	LSFT(DV_0)
+#define DV_LCBR	LSFT(DV_LBRC)
+#define DV_RCBR	LSFT(DV_RBRC)
+
+#endif
\ No newline at end of file
diff --git a/quantum/keymap_extras/keymap_french.h b/quantum/keymap_extras/keymap_french.h
new file mode 100644
index 0000000000..ccfaed8f07
--- /dev/null
+++ b/quantum/keymap_extras/keymap_french.h
@@ -0,0 +1,83 @@
+#ifndef KEYMAP_FRENCH_H
+#define KEYMAP_FRENCH_H
+
+#include "keymap_common.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define NO_ALGR KC_RALT
+
+// Normal characters
+#define FR_SUP2	KC_GRV
+#define FR_AMP	KC_1
+#define FR_EACU	KC_2
+#define FR_QUOT	KC_3
+#define FR_APOS	KC_4
+#define FR_LPRN	KC_5
+#define FR_MINS	KC_6
+#define FR_EGRV	KC_7
+#define FR_UNDS	KC_8
+#define FR_CCED	KC_9
+#define FR_AGRV	KC_0
+#define FR_RPRN	KC_MINS
+#define FR_EQL	KC_EQL
+
+#define FR_A 	KC_Q
+#define FR_Z	KC_W
+#define	FR_CIRC	KC_LBRC
+#define FR_DLR	KC_RBRC
+
+#define FR_Q 	KC_A
+#define FR_M 	KC_SCLN
+#define FR_UGRV	KC_QUOT
+#define FR_ASTR	KC_NUHS
+
+#define FR_LESS	KC_NUBS
+#define FR_W	KC_Z
+#define FR_COMM	KC_M
+#define FR_SCLN	KC_COMM
+#define FR_COLN	KC_DOT
+#define FR_EXLM	KC_SLSH
+
+// Shifted characters
+#define FR_1 	LSFT(KC_1)
+#define FR_2 	LSFT(KC_2)
+#define FR_3 	LSFT(KC_3)
+#define FR_4 	LSFT(KC_4)
+#define FR_5 	LSFT(KC_5)
+#define FR_6 	LSFT(KC_6)
+#define FR_7 	LSFT(KC_7)
+#define FR_8 	LSFT(KC_8)
+#define FR_9 	LSFT(KC_9)
+#define FR_0 	LSFT(KC_0)
+#define FR_OVRR	LSFT(FR_RPRN)
+#define FR_PLUS LSFT(FR_EQL)
+
+#define FR_UMLT	LSFT(FR_CIRC)
+#define FR_PND	LSFT(FR_DLR)
+#define	FR_PERC	LSFT(FR_UGRV)
+#define FR_MU 	LSFT(FR_ASTR)
+
+#define FR_GRTR	LSFT(FR_LESS)
+#define FR_QUES	LSFT(FR_COMM)
+#define FR_DOT	LSFT(FR_SCLN)
+#define FR_SLSH	LSFT(FR_COLN)
+#define FR_SECT	LSFT(FR_EXLM)
+
+// Alt Gr-ed characters
+#define FR_TILD	ALGR(KC_2)
+#define FR_HASH	ALGR(KC_3)
+#define FR_LCBR ALGR(KC_4)
+#define FR_LBRC	ALGR(KC_5)
+#define FR_PIPE ALGR(KC_6)
+#define FR_GRV 	ALGR(KC_7)
+#define FR_BSLS	ALGR(KC_8)
+#define FR_CIRC	ALGR(KC_9)
+#define FR_AT 	ALGR(KC_0)
+#define FR_RBRC	ALGR(FR_RPRN)
+#define FR_LCBR ALGR(FR_EQL)
+
+#define FR_EURO	ALGR(KC_E)
+#define FR_BULT	ALGR(FR_DLR)
+
+#endif
\ No newline at end of file
diff --git a/quantum/keymap_extras/keymap_nordic.h b/quantum/keymap_extras/keymap_nordic.h
new file mode 100644
index 0000000000..02a704216a
--- /dev/null
+++ b/quantum/keymap_extras/keymap_nordic.h
@@ -0,0 +1,59 @@
+#ifndef KEYMAP_NORDIC_H
+#define KEYMAP_NORDIC_H
+
+#include "keymap_common.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define NO_ALGR KC_RALT
+
+// Normal characters
+#define NO_HALF	KC_GRV
+#define NO_PLUS	KC_MINS
+#define NO_ACUT	KC_EQL
+
+#define NO_AM	KC_LBRC
+#define NO_QUOT	KC_RBRC
+#define NO_AE	KC_SCLN
+#define NO_OSLH	KC_QUOT
+#define	NO_APOS	KC_NUHS
+
+#define NO_LESS	KC_NUBS
+#define NO_MINS KC_SLSH
+
+// Shifted characters
+#define NO_SECT LSFT(NO_HALF)
+#define NO_QUO2	LSFT(KC_2)
+#define NO_BULT LSFT(KC_4)
+#define NO_AMP	LSFT(KC_6)
+#define NO_SLSH LSFT(KC_7)
+#define NO_LPRN	LSFT(KC_8)
+#define NO_RPRN	LSFT(KC_9)
+#define NO_EQL	LSFT(KC_0)
+#define NO_QUES	LSFT(NO_PLUS)
+#define NO_GRV	LSFT(NO_ACUT)
+
+#define NO_CIRC LSFT(NO_QUOT)
+
+#define NO_GRTR	LSFT(NO_LESS)
+#define NO_SCLN LSFT(KC_COMM)
+#define NO_COLN LSFT(KC_DOT)
+#define NO_UNDS LSFT(NO_MINS)
+
+// Alt Gr-ed characters
+#define NO_AT	ALGR(KC_2)
+#define NO_PND	ALGR(KC_3)
+#define NO_DLR	ALGR(KC_4)
+#define NO_LCBR ALGR(KC_7)
+#define NO_LBRC ALGR(KC_8)
+#define NO_RBRC ALGR(KC_9)
+#define NO_RCBR	ALGR(KC_0)
+#define NO_PIPE ALGR(NO_ACUT)
+
+#define NO_EURO ALGR(KC_E)
+#define NO_TILD ALGR(NO_QUOT)
+
+#define NO_BSLS ALGR(NO_LESS)
+#define NO_MU 	ALGR(KC_M)
+
+#endif
\ No newline at end of file
diff --git a/quantum/keymap_extras/keymap_spanish.h b/quantum/keymap_extras/keymap_spanish.h
new file mode 100644
index 0000000000..7f980afbcf
--- /dev/null
+++ b/quantum/keymap_extras/keymap_spanish.h
@@ -0,0 +1,62 @@
+#ifndef KEYMAP_SPANISH_H
+#define KEYMAP_SPANISH_H
+
+#include "keymap_common.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define NO_ALGR KC_RALT
+
+// Normal characters
+#define ES_OVRR KC_GRV
+#define ES_APOS	KC_MINS
+#define ES_IEXL	KC_EQL
+
+#define ES_GRV	KC_LBRC
+#define ES_PLUS	KC_RBRC
+
+#define ES_NTIL	KC_SCLN
+#define ES_ACUT	KC_QUOT
+#define ES_CCED	KC_NUHS
+
+#define ES_LESS	KC_NUBS
+#define ES_MINS	KC_SLSH
+
+// Shifted characters
+#define ES_ASML	LSFT(ES_OVRR)
+#define ES_QUOT	LSFT(KC_2)
+#define ES_OVDT	LSFT(KC_3)
+#define ES_AMPR	LSFT(KC_6)
+#define ES_SLSH LSFT(KC_7)
+#define ES_LPRN LSFT(KC_8)
+#define ES_RPRN LSFT(KC_9)
+#define ES_EQL	LSFT(KC_0)
+#define ES_QUES	LSFT(ES_APOS)
+#define ES_IQUE	LSFT(ES_IEXL)
+
+#define ES_CIRC	LSFT(ES_GRV)
+#define ES_ASTR	LSFT(ES_PLUS)
+
+#define ES_UMLT	LSFT(ES_GRV)
+
+#define ES_GRTR	LSFT(ES_LESS)
+#define ES_SCLN	LSFT(ES_COMM)
+#define ES_COLN	LSFT(ES_DOT)
+#define ES_UNDS	LSFT(ES_MINS)
+
+// Alt Gr-ed characters
+#define ES_BSLS	ALGR(ES_OVRR)
+#define ES_PIPE	ALGR(KC_1)
+#define ES_AT 	ALGR(KC_2)
+#define ES_HASH	ALGR(KC_3)
+#define ES_TILD	ALGR(KC_4)
+#define ES_EURO	ALGR(KC_5)
+#define ES_NOT	ALGR(KC_6)
+
+#define ES_LBRC	ALGR(ES_GRV)
+#define ES_RBRC ALGR(ES_PLUS)
+
+#define ES_LCBR	ALGR(ES_ACUT)
+#define ES_RCRB	ALGR(ES_CCED)
+
+#endif
\ No newline at end of file
diff --git a/quantum/keymap_extras/keymap_uk.h b/quantum/keymap_extras/keymap_uk.h
new file mode 100644
index 0000000000..5b4bd3c0d4
--- /dev/null
+++ b/quantum/keymap_extras/keymap_uk.h
@@ -0,0 +1,36 @@
+#ifndef KEYMAP_UK_H
+#define KEYMAP_UK_H
+
+#include "keymap_common.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define NO_ALGR KC_RALT
+
+// Normal characters
+#define UK_HASH KC_NUHS
+
+#define UK_BSLS	KC_NUBS
+
+// Shifted characters
+#define UK_NOT	LSFT(KC_GRV)
+#define UK_QUOT	LSFT(KC_2)
+#define UK_PND	LSFT(KC_3)
+
+#define UK_AT	LSFT(KC_QUOT)
+#define UK_TILD	LSFT(KC_NUHS)
+
+#define UK_PIPE	LSFT(KC_NUBS)
+
+// Alt Gr-ed characters
+#define UK_BRKP	ALGR(KC_GRV)
+#define UK_EURO	ALGR(KC_4)
+
+#define UK_EACT	ALGR(KC_E)
+#define UK_UACT	ALGR(KC_U)
+#define UK_IACT ALGR(KC_I)
+#define UK_OACT ALGR(KC_O)
+
+#define UK_AACT ALGR(KC_A)
+
+#endif
\ No newline at end of file
diff --git a/quantum/keymap_midi.c b/quantum/keymap_midi.c
new file mode 100644
index 0000000000..b7eba3ab76
--- /dev/null
+++ b/quantum/keymap_midi.c
@@ -0,0 +1,110 @@
+/*
+Copyright 2015 Jack Humbert <jack.humb@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 "keymap_common.h"
+#include "keymap_midi.h"
+#include <lufa.h>
+
+uint8_t starting_note = 0x0C;
+int offset = 7;
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+	if (id != 0) {
+	    if (record->event.pressed) {
+	    	midi_send_noteon(&midi_device, opt, (id & 0xFF), 127);
+	    } else {
+	        midi_send_noteoff(&midi_device, opt, (id & 0xFF), 127);
+	    }
+	}
+
+    if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
+        if (record->event.pressed) {
+            starting_note++;
+            play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
+            midi_send_cc(&midi_device, 0, 0x7B, 0);
+            midi_send_cc(&midi_device, 1, 0x7B, 0);
+            midi_send_cc(&midi_device, 2, 0x7B, 0);
+            midi_send_cc(&midi_device, 3, 0x7B, 0);
+            midi_send_cc(&midi_device, 4, 0x7B, 0);
+            return;
+        } else {
+            stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
+            stop_all_notes();
+            return;
+        }
+    }
+    if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
+        if (record->event.pressed) {
+            starting_note--;
+            play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
+            midi_send_cc(&midi_device, 0, 0x7B, 0);
+            midi_send_cc(&midi_device, 1, 0x7B, 0);
+            midi_send_cc(&midi_device, 2, 0x7B, 0);
+            midi_send_cc(&midi_device, 3, 0x7B, 0);
+            midi_send_cc(&midi_device, 4, 0x7B, 0);
+            return;
+        } else {
+            stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
+            stop_all_notes();
+            return;
+        }
+    }
+
+    if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
+        offset++;
+        midi_send_cc(&midi_device, 0, 0x7B, 0);
+        midi_send_cc(&midi_device, 1, 0x7B, 0);
+        midi_send_cc(&midi_device, 2, 0x7B, 0);
+        midi_send_cc(&midi_device, 3, 0x7B, 0);
+        midi_send_cc(&midi_device, 4, 0x7B, 0);
+        stop_all_notes();
+        for (int i = 0; i <= 7; i++) {
+            play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
+            _delay_us(80000);
+            stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
+            _delay_us(8000);
+        }
+        return;
+    }
+    if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
+        offset--;
+        midi_send_cc(&midi_device, 0, 0x7B, 0);
+        midi_send_cc(&midi_device, 1, 0x7B, 0);
+        midi_send_cc(&midi_device, 2, 0x7B, 0);
+        midi_send_cc(&midi_device, 3, 0x7B, 0);
+        midi_send_cc(&midi_device, 4, 0x7B, 0);
+        stop_all_notes();
+        for (int i = 0; i <= 7; i++) {
+            play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
+            _delay_us(80000);
+            stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
+            _delay_us(8000);
+        }
+        return;
+    }
+
+    if (record->event.pressed) {
+    	// midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
+        midi_send_noteon(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
+        play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF);
+    } else {
+        // midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
+        midi_send_noteoff(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
+        stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)));
+    }
+}
\ No newline at end of file
diff --git a/quantum/keymap_midi.h b/quantum/keymap_midi.h
new file mode 100644
index 0000000000..c5917f884e
--- /dev/null
+++ b/quantum/keymap_midi.h
@@ -0,0 +1,220 @@
+/*
+Copyright 2015 Jack Humbert <jack.humb@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEYMAP_MIDI_H
+#define KEYMAP_MIDI_H
+
+#define MIDI 0x6000
+#define MIDI12 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000
+
+#define CHNL(note, channel) (note + (channel << 8))
+
+#define SCALE (int []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
+						0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
+						0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
+						0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
+						0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
+
+#define N_CN1  (0x600C + (12 * -1) + 0 )
+#define N_CN1S (0x600C + (12 * -1) + 1 )
+#define N_DN1F (0x600C + (12 * -1) + 1 )
+#define N_DN1  (0x600C + (12 * -1) + 2 )
+#define N_DN1S (0x600C + (12 * -1) + 3 )
+#define N_EN1F (0x600C + (12 * -1) + 3 )
+#define N_EN1  (0x600C + (12 * -1) + 4 )
+#define N_FN1  (0x600C + (12 * -1) + 5 )
+#define N_FN1S (0x600C + (12 * -1) + 6 )
+#define N_GN1F (0x600C + (12 * -1) + 6 )
+#define N_GN1  (0x600C + (12 * -1) + 7 )
+#define N_GN1S (0x600C + (12 * -1) + 8 )
+#define N_AN1F (0x600C + (12 * -1) + 8 )
+#define N_AN1  (0x600C + (12 * -1) + 9 )
+#define N_AN1S (0x600C + (12 * -1) + 10)
+#define N_BN1F (0x600C + (12 * -1) + 10)
+#define N_BN1  (0x600C + (12 * -1) + 11)
+#define N_C0   (0x600C + (12 *  0) + 0 )
+#define N_C0S  (0x600C + (12 *  0) + 1 )
+#define N_D0F  (0x600C + (12 *  0) + 1 )
+#define N_D0   (0x600C + (12 *  0) + 2 )
+#define N_D0S  (0x600C + (12 *  0) + 3 )
+#define N_E0F  (0x600C + (12 *  0) + 3 )
+#define N_E0   (0x600C + (12 *  0) + 4 )
+#define N_F0   (0x600C + (12 *  0) + 5 )
+#define N_F0S  (0x600C + (12 *  0) + 6 )
+#define N_G0F  (0x600C + (12 *  0) + 6 )
+#define N_G0   (0x600C + (12 *  0) + 7 )
+#define N_G0S  (0x600C + (12 *  0) + 8 )
+#define N_A0F  (0x600C + (12 *  0) + 8 )
+#define N_A0   (0x600C + (12 *  0) + 9 )
+#define N_A0S  (0x600C + (12 *  0) + 10)
+#define N_B0F  (0x600C + (12 *  0) + 10)
+#define N_B0   (0x600C + (12 *  0) + 11)
+#define N_C1   (0x600C + (12 *  1) + 0 )
+#define N_C1S  (0x600C + (12 *  1) + 1 )
+#define N_D1F  (0x600C + (12 *  1) + 1 )
+#define N_D1   (0x600C + (12 *  1) + 2 )
+#define N_D1S  (0x600C + (12 *  1) + 3 )
+#define N_E1F  (0x600C + (12 *  1) + 3 )
+#define N_E1   (0x600C + (12 *  1) + 4 )
+#define N_F1   (0x600C + (12 *  1) + 5 )
+#define N_F1S  (0x600C + (12 *  1) + 6 )
+#define N_G1F  (0x600C + (12 *  1) + 6 )
+#define N_G1   (0x600C + (12 *  1) + 7 )
+#define N_G1S  (0x600C + (12 *  1) + 8 )
+#define N_A1F  (0x600C + (12 *  1) + 8 )
+#define N_A1   (0x600C + (12 *  1) + 9 )
+#define N_A1S  (0x600C + (12 *  1) + 10)
+#define N_B1F  (0x600C + (12 *  1) + 10)
+#define N_B1   (0x600C + (12 *  1) + 11)
+#define N_C2   (0x600C + (12 *  2) + 0 )
+#define N_C2S  (0x600C + (12 *  2) + 1 )
+#define N_D2F  (0x600C + (12 *  2) + 1 )
+#define N_D2   (0x600C + (12 *  2) + 2 )
+#define N_D2S  (0x600C + (12 *  2) + 3 )
+#define N_E2F  (0x600C + (12 *  2) + 3 )
+#define N_E2   (0x600C + (12 *  2) + 4 )
+#define N_F2   (0x600C + (12 *  2) + 5 )
+#define N_F2S  (0x600C + (12 *  2) + 6 )
+#define N_G2F  (0x600C + (12 *  2) + 6 )
+#define N_G2   (0x600C + (12 *  2) + 7 )
+#define N_G2S  (0x600C + (12 *  2) + 8 )
+#define N_A2F  (0x600C + (12 *  2) + 8 )
+#define N_A2   (0x600C + (12 *  2) + 9 )
+#define N_A2S  (0x600C + (12 *  2) + 10)
+#define N_B2F  (0x600C + (12 *  2) + 10)
+#define N_B2   (0x600C + (12 *  2) + 11)
+#define N_C3   (0x600C + (12 *  3) + 0 )
+#define N_C3S  (0x600C + (12 *  3) + 1 )
+#define N_D3F  (0x600C + (12 *  3) + 1 )
+#define N_D3   (0x600C + (12 *  3) + 2 )
+#define N_D3S  (0x600C + (12 *  3) + 3 )
+#define N_E3F  (0x600C + (12 *  3) + 3 )
+#define N_E3   (0x600C + (12 *  3) + 4 )
+#define N_F3   (0x600C + (12 *  3) + 5 )
+#define N_F3S  (0x600C + (12 *  3) + 6 )
+#define N_G3F  (0x600C + (12 *  3) + 6 )
+#define N_G3   (0x600C + (12 *  3) + 7 )
+#define N_G3S  (0x600C + (12 *  3) + 8 )
+#define N_A3F  (0x600C + (12 *  3) + 8 )
+#define N_A3   (0x600C + (12 *  3) + 9 )
+#define N_A3S  (0x600C + (12 *  3) + 10)
+#define N_B3F  (0x600C + (12 *  3) + 10)
+#define N_B3   (0x600C + (12 *  3) + 11)
+#define N_C4   (0x600C + (12 *  4) + 0 )
+#define N_C4S  (0x600C + (12 *  4) + 1 )
+#define N_D4F  (0x600C + (12 *  4) + 1 )
+#define N_D4   (0x600C + (12 *  4) + 2 )
+#define N_D4S  (0x600C + (12 *  4) + 3 )
+#define N_E4F  (0x600C + (12 *  4) + 3 )
+#define N_E4   (0x600C + (12 *  4) + 4 )
+#define N_F4   (0x600C + (12 *  4) + 5 )
+#define N_F4S  (0x600C + (12 *  4) + 6 )
+#define N_G4F  (0x600C + (12 *  4) + 6 )
+#define N_G4   (0x600C + (12 *  4) + 7 )
+#define N_G4S  (0x600C + (12 *  4) + 8 )
+#define N_A4F  (0x600C + (12 *  4) + 8 )
+#define N_A4   (0x600C + (12 *  4) + 9 )
+#define N_A4S  (0x600C + (12 *  4) + 10)
+#define N_B4F  (0x600C + (12 *  4) + 10)
+#define N_B4   (0x600C + (12 *  4) + 11)
+#define N_C5   (0x600C + (12 *  5) + 0 )
+#define N_C5S  (0x600C + (12 *  5) + 1 )
+#define N_D5F  (0x600C + (12 *  5) + 1 )
+#define N_D5   (0x600C + (12 *  5) + 2 )
+#define N_D5S  (0x600C + (12 *  5) + 3 )
+#define N_E5F  (0x600C + (12 *  5) + 3 )
+#define N_E5   (0x600C + (12 *  5) + 4 )
+#define N_F5   (0x600C + (12 *  5) + 5 )
+#define N_F5S  (0x600C + (12 *  5) + 6 )
+#define N_G5F  (0x600C + (12 *  5) + 6 )
+#define N_G5   (0x600C + (12 *  5) + 7 )
+#define N_G5S  (0x600C + (12 *  5) + 8 )
+#define N_A5F  (0x600C + (12 *  5) + 8 )
+#define N_A5   (0x600C + (12 *  5) + 9 )
+#define N_A5S  (0x600C + (12 *  5) + 10)
+#define N_B5F  (0x600C + (12 *  5) + 10)
+#define N_B5   (0x600C + (12 *  5) + 11)
+#define N_C6   (0x600C + (12 *  6) + 0 )
+#define N_C6S  (0x600C + (12 *  6) + 1 )
+#define N_D6F  (0x600C + (12 *  6) + 1 )
+#define N_D6   (0x600C + (12 *  6) + 2 )
+#define N_D6S  (0x600C + (12 *  6) + 3 )
+#define N_E6F  (0x600C + (12 *  6) + 3 )
+#define N_E6   (0x600C + (12 *  6) + 4 )
+#define N_F6   (0x600C + (12 *  6) + 5 )
+#define N_F6S  (0x600C + (12 *  6) + 6 )
+#define N_G6F  (0x600C + (12 *  6) + 6 )
+#define N_G6   (0x600C + (12 *  6) + 7 )
+#define N_G6S  (0x600C + (12 *  6) + 8 )
+#define N_A6F  (0x600C + (12 *  6) + 8 )
+#define N_A6   (0x600C + (12 *  6) + 9 )
+#define N_A6S  (0x600C + (12 *  6) + 10)
+#define N_B6F  (0x600C + (12 *  6) + 10)
+#define N_B6   (0x600C + (12 *  6) + 11)
+#define N_C7   (0x600C + (12 *  7) + 0 )
+#define N_C7S  (0x600C + (12 *  7) + 1 )
+#define N_D7F  (0x600C + (12 *  7) + 1 )
+#define N_D7   (0x600C + (12 *  7) + 2 )
+#define N_D7S  (0x600C + (12 *  7) + 3 )
+#define N_E7F  (0x600C + (12 *  7) + 3 )
+#define N_E7   (0x600C + (12 *  7) + 4 )
+#define N_F7   (0x600C + (12 *  7) + 5 )
+#define N_F7S  (0x600C + (12 *  7) + 6 )
+#define N_G7F  (0x600C + (12 *  7) + 6 )
+#define N_G7   (0x600C + (12 *  7) + 7 )
+#define N_G7S  (0x600C + (12 *  7) + 8 )
+#define N_A7F  (0x600C + (12 *  7) + 8 )
+#define N_A7   (0x600C + (12 *  7) + 9 )
+#define N_A7S  (0x600C + (12 *  7) + 10)
+#define N_B7F  (0x600C + (12 *  7) + 10)
+#define N_B7   (0x600C + (12 *  7) + 11)
+#define N_C8   (0x600C + (12 *  8) + 0 )
+#define N_C8S  (0x600C + (12 *  8) + 1 )
+#define N_D8F  (0x600C + (12 *  8) + 1 )
+#define N_D8   (0x600C + (12 *  8) + 2 )
+#define N_D8S  (0x600C + (12 *  8) + 3 )
+#define N_E8F  (0x600C + (12 *  8) + 3 )
+#define N_E8   (0x600C + (12 *  8) + 4 )
+#define N_F8   (0x600C + (12 *  8) + 5 )
+#define N_F8S  (0x600C + (12 *  8) + 6 )
+#define N_G8F  (0x600C + (12 *  8) + 6 )
+#define N_G8   (0x600C + (12 *  8) + 7 )
+#define N_G8S  (0x600C + (12 *  8) + 8 )
+#define N_A8F  (0x600C + (12 *  8) + 8 )
+#define N_A8   (0x600C + (12 *  8) + 9 )
+#define N_A8S  (0x600C + (12 *  8) + 10)
+#define N_B8F  (0x600C + (12 *  8) + 10)
+#define N_B8   (0x600C + (12 *  8) + 11)
+#define N_C8   (0x600C + (12 *  8) + 0 )
+#define N_C8S  (0x600C + (12 *  8) + 1 )
+#define N_D8F  (0x600C + (12 *  8) + 1 )
+#define N_D8   (0x600C + (12 *  8) + 2 )
+#define N_D8S  (0x600C + (12 *  8) + 3 )
+#define N_E8F  (0x600C + (12 *  8) + 3 )
+#define N_E8   (0x600C + (12 *  8) + 4 )
+#define N_F8   (0x600C + (12 *  8) + 5 )
+#define N_F8S  (0x600C + (12 *  8) + 6 )
+#define N_G8F  (0x600C + (12 *  8) + 6 )
+#define N_G8   (0x600C + (12 *  8) + 7 )
+#define N_G8S  (0x600C + (12 *  8) + 8 )
+#define N_A8F  (0x600C + (12 *  8) + 8 )
+#define N_A8   (0x600C + (12 *  8) + 9 )
+#define N_A8S  (0x600C + (12 *  8) + 10)
+#define N_B8F  (0x600C + (12 *  8) + 10)
+#define N_B8   (0x600C + (12 *  8) + 11)
+
+#endif
\ No newline at end of file
diff --git a/quantum/keymap_unicode.c b/quantum/keymap_unicode.c
new file mode 100644
index 0000000000..a9357edec7
--- /dev/null
+++ b/quantum/keymap_unicode.c
@@ -0,0 +1,59 @@
+/*
+Copyright 2015 Jack Humbert <jack.humb@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 "keymap_common.h"
+
+uint16_t hextokeycode(int hex) {
+    if (hex == 0x0) {
+        return KC_0;
+    } else if (hex < 0xA) {
+        return KC_1 + (hex - 0x1);
+    } else {
+        return KC_A + (hex - 0xA);
+    }
+}
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+
+    if (record->event.pressed) {
+        uint16_t unicode = (opt << 8) | id;
+        register_code(KC_LALT);
+
+        register_code(hextokeycode((unicode & 0xF000) >> 12));
+        unregister_code(hextokeycode((unicode & 0xF000) >> 12));
+        register_code(hextokeycode((unicode & 0x0F00) >> 8));
+        unregister_code(hextokeycode((unicode & 0x0F00) >> 8));
+        register_code(hextokeycode((unicode & 0x00F0) >> 4));
+        unregister_code(hextokeycode((unicode & 0x00F0) >> 4));
+        register_code(hextokeycode((unicode & 0x000F)));
+        unregister_code(hextokeycode((unicode & 0x000F)));
+        
+        /* Test 'a' */
+        // register_code(hextokeycode(0x0));
+        // unregister_code(hextokeycode(0x0));
+        // register_code(hextokeycode(0x0));
+        // unregister_code(hextokeycode(0x0));
+        // register_code(hextokeycode(0x6));
+        // unregister_code(hextokeycode(0x6));
+        // register_code(hextokeycode(0x1));
+        // unregister_code(hextokeycode(0x1));
+
+        unregister_code(KC_LALT);
+    }
+    return;
+}
\ No newline at end of file
diff --git a/quantum/led.c b/quantum/led.c
new file mode 100644
index 0000000000..2c05746607
--- /dev/null
+++ b/quantum/led.c
@@ -0,0 +1,38 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <avr/io.h>
+#include "stdint.h"
+#include "led.h"
+
+
+void led_set(uint8_t usb_led)
+{
+    // // Using PE6 Caps Lock LED
+    // if (usb_led & (1<<USB_LED_CAPS_LOCK))
+    // {
+    //     // Output high.
+    //     DDRE |= (1<<6);
+    //     PORTE |= (1<<6);
+    // }
+    // else
+    // {
+    //     // Output low.
+    //     DDRE &= ~(1<<6);
+    //     PORTE &= ~(1<<6);
+    // }
+}
diff --git a/quantum/matrix.c b/quantum/matrix.c
new file mode 100644
index 0000000000..97642a4a4e
--- /dev/null
+++ b/quantum/matrix.c
@@ -0,0 +1,301 @@
+/*
+Copyright 2012 Jun Wako 
+Generated by planckkeyboard.com (2014 Jack Humbert)
+
+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 "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+
+#ifndef DEBOUNCE
+#   define DEBOUNCE 10
+#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];
+
+#if DIODE_DIRECTION == ROW2COL
+    static matrix_row_t matrix_reversed[MATRIX_COLS];
+    static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
+#endif
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(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)
+{
+    // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
+    MCUCR |= (1<<JTD);
+    MCUCR |= (1<<JTD);
+
+
+    // initialize row and col
+    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;
+    }
+
+    if (matrix_init_kb) {
+        (*matrix_init_kb)();
+    }
+}
+
+
+uint8_t matrix_scan(void)
+{
+
+#if DIODE_DIRECTION == COL2ROW
+    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+        select_row(i);
+        _delay_us(30);  // without this wait read unstable value.
+        matrix_row_t cols = read_cols();
+        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];
+            }
+        }
+    }
+#else
+    for (uint8_t i = 0; i < MATRIX_COLS; i++) {
+        select_row(i);
+        _delay_us(30);  // without this wait read unstable value.
+        matrix_row_t rows = read_cols();
+        if (matrix_reversed_debouncing[i] != rows) {
+            matrix_reversed_debouncing[i] = rows;
+            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_COLS; i++) {
+                matrix_reversed[i] = matrix_reversed_debouncing[i];
+            }
+        }
+    }
+    for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
+        matrix_row_t row = 0;
+        for (uint8_t x = 0; x < MATRIX_COLS; x++) {
+            row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
+        }
+        matrix[y] = row;
+    }
+#endif
+
+    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;
+}
+
+static void init_cols(void)
+{
+    int B = 0, C = 0, D = 0, E = 0, F = 0;
+
+#if DIODE_DIRECTION == COL2ROW
+    for(int x = 0; x < MATRIX_COLS; x++) {
+        int col = COLS[x];
+#else
+    for(int x = 0; x < MATRIX_ROWS; x++) {
+        int col = ROWS[x];
+#endif
+        if ((col & 0xF0) == 0x20) { 
+            B |= (1<<(col & 0x0F)); 
+        } else if ((col & 0xF0) == 0x30) { 
+            C |= (1<<(col & 0x0F)); 
+        } else if ((col & 0xF0) == 0x40) { 
+            D |= (1<<(col & 0x0F)); 
+        } else if ((col & 0xF0) == 0x50) { 
+            E |= (1<<(col & 0x0F)); 
+        } else if ((col & 0xF0) == 0x60) { 
+            F |= (1<<(col & 0x0F)); 
+        } 
+    }
+    DDRB &= ~(B); PORTB |= (B);
+    DDRC &= ~(C); PORTC |= (C); 
+    DDRD &= ~(D); PORTD |= (D);
+    DDRE &= ~(E); PORTE |= (E);
+    DDRF &= ~(F); PORTF |= (F);
+}
+
+static matrix_row_t read_cols(void)
+{
+    matrix_row_t result = 0;
+
+#if DIODE_DIRECTION == COL2ROW
+    for(int x = 0; x < MATRIX_COLS; x++) {     
+        int col = COLS[x];
+#else
+    for(int x = 0; x < MATRIX_ROWS; x++) {
+        int col = ROWS[x];
+#endif
+
+        if ((col & 0xF0) == 0x20) { 
+            result |= (PINB&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
+        } else if ((col & 0xF0) == 0x30) { 
+            result |= (PINC&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
+        } else if ((col & 0xF0) == 0x40) { 
+            result |= (PIND&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
+        } else if ((col & 0xF0) == 0x50) { 
+            result |= (PINE&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
+        } else if ((col & 0xF0) == 0x60) { 
+            result |= (PINF&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
+        } 
+    }
+    return result;
+}
+
+static void unselect_rows(void)
+{
+    int B = 0, C = 0, D = 0, E = 0, F = 0;
+
+#if DIODE_DIRECTION == COL2ROW
+    for(int x = 0; x < MATRIX_ROWS; x++) { 
+        int row = ROWS[x];
+#else
+    for(int x = 0; x < MATRIX_COLS; x++) { 
+        int row = COLS[x];
+#endif
+        if ((row & 0xF0) == 0x20) { 
+            B |= (1<<(row & 0x0F)); 
+        } else if ((row & 0xF0) == 0x30) { 
+            C |= (1<<(row & 0x0F)); 
+        } else if ((row & 0xF0) == 0x40) { 
+            D |= (1<<(row & 0x0F)); 
+        } else if ((row & 0xF0) == 0x50) { 
+            E |= (1<<(row & 0x0F)); 
+        } else if ((row & 0xF0) == 0x60) { 
+            F |= (1<<(row & 0x0F)); 
+        } 
+    }
+    DDRB &= ~(B); PORTB |= (B);
+    DDRC &= ~(C); PORTC |= (C); 
+    DDRD &= ~(D); PORTD |= (D);
+    DDRE &= ~(E); PORTE |= (E);
+    DDRF &= ~(F); PORTF |= (F);
+}
+
+static void select_row(uint8_t row)
+{
+
+#if DIODE_DIRECTION == COL2ROW
+    int row_pin = ROWS[row];
+#else
+    int row_pin = COLS[row];
+#endif
+
+    if ((row_pin & 0xF0) == 0x20) { 
+        DDRB  |= (1<<(row_pin & 0x0F));
+        PORTB &= ~(1<<(row_pin & 0x0F));
+    } else if ((row_pin & 0xF0) == 0x30) { 
+        DDRC  |= (1<<(row_pin & 0x0F));
+        PORTC &= ~(1<<(row_pin & 0x0F));
+    } else if ((row_pin & 0xF0) == 0x40) { 
+        DDRD  |= (1<<(row_pin & 0x0F));
+        PORTD &= ~(1<<(row_pin & 0x0F));
+    } else if ((row_pin & 0xF0) == 0x50) { 
+        DDRE  |= (1<<(row_pin & 0x0F));
+        PORTE &= ~(1<<(row_pin & 0x0F));
+    } else if ((row_pin & 0xF0) == 0x60) { 
+        DDRF  |= (1<<(row_pin & 0x0F));
+        PORTF &= ~(1<<(row_pin & 0x0F));
+    }  
+}
\ No newline at end of file