summaryrefslogtreecommitdiff
path: root/keyboards/woodkeys/meira
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/woodkeys/meira')
-rwxr-xr-xkeyboards/woodkeys/meira/TWIlib.c300
-rwxr-xr-xkeyboards/woodkeys/meira/TWIlib.h71
-rw-r--r--keyboards/woodkeys/meira/config.h45
-rw-r--r--keyboards/woodkeys/meira/featherble/config.h97
-rw-r--r--keyboards/woodkeys/meira/featherble/featherble.c17
-rw-r--r--keyboards/woodkeys/meira/featherble/featherble.h19
-rw-r--r--keyboards/woodkeys/meira/featherble/rules.mk5
-rw-r--r--keyboards/woodkeys/meira/info.json65
-rwxr-xr-xkeyboards/woodkeys/meira/issi.c286
-rwxr-xr-xkeyboards/woodkeys/meira/issi.h39
-rw-r--r--keyboards/woodkeys/meira/keymaps/cole/config.h31
-rw-r--r--keyboards/woodkeys/meira/keymaps/cole/keymap.c225
-rw-r--r--keyboards/woodkeys/meira/keymaps/cole/readme.md1
-rw-r--r--keyboards/woodkeys/meira/keymaps/cole/rules.mk2
-rw-r--r--keyboards/woodkeys/meira/keymaps/default/config.h31
-rw-r--r--keyboards/woodkeys/meira/keymaps/default/keymap.c299
-rw-r--r--keyboards/woodkeys/meira/keymaps/default/readme.md1
-rw-r--r--keyboards/woodkeys/meira/keymaps/grahampheath/config.h35
-rw-r--r--keyboards/woodkeys/meira/keymaps/grahampheath/keymap.c398
-rw-r--r--keyboards/woodkeys/meira/keymaps/grahampheath/readme.md55
-rw-r--r--keyboards/woodkeys/meira/keymaps/grahampheath/rules.mk5
-rw-r--r--keyboards/woodkeys/meira/keymaps/takmiya/config.h24
-rw-r--r--keyboards/woodkeys/meira/keymaps/takmiya/keymap.c234
-rw-r--r--keyboards/woodkeys/meira/keymaps/takmiya/readme.md1
-rwxr-xr-xkeyboards/woodkeys/meira/lighting.c97
-rwxr-xr-xkeyboards/woodkeys/meira/lighting.h6
-rw-r--r--keyboards/woodkeys/meira/matrix.c270
-rw-r--r--keyboards/woodkeys/meira/meira.c97
-rw-r--r--keyboards/woodkeys/meira/meira.h37
-rw-r--r--keyboards/woodkeys/meira/promicro/config.h88
-rw-r--r--keyboards/woodkeys/meira/promicro/promicro.c17
-rw-r--r--keyboards/woodkeys/meira/promicro/promicro.h19
-rw-r--r--keyboards/woodkeys/meira/promicro/rules.mk3
-rw-r--r--keyboards/woodkeys/meira/readme.md28
-rw-r--r--keyboards/woodkeys/meira/rules.mk34
35 files changed, 2982 insertions, 0 deletions
diff --git a/keyboards/woodkeys/meira/TWIlib.c b/keyboards/woodkeys/meira/TWIlib.c
new file mode 100755
index 0000000000..8f5658fcdb
--- /dev/null
+++ b/keyboards/woodkeys/meira/TWIlib.c
@@ -0,0 +1,300 @@
+/*
+ * TWIlib.c
+ *
+ * Created: 6/01/2014 10:41:33 PM
+ * Author: Chris Herring
+ */
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "TWIlib.h"
+#include <util/delay.h>
+#include "print.h"
+
+// Global transmit buffer
+volatile uint8_t *TWITransmitBuffer;
+// Global receive buffer
+volatile uint8_t TWIReceiveBuffer[RXMAXBUFLEN];
+// Buffer indexes
+volatile int TXBuffIndex; // Index of the transmit buffer. Is volatile, can change at any time.
+int RXBuffIndex; // Current index in the receive buffer
+// Buffer lengths
+int TXBuffLen; // The total length of the transmit buffer
+int RXBuffLen; // The total number of bytes to read (should be less than RXMAXBUFFLEN)
+
+TWIInfoStruct TWIInfo;
+
+void TWIInit()
+{
+ TWIInfo.mode = Ready;
+ TWIInfo.errorCode = 0xFF;
+ TWIInfo.repStart = 0;
+ // Set pre-scalers (no pre-scaling)
+ TWSR = 0;
+ // Set bit rate
+ TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
+ // Enable TWI and interrupt
+ TWCR = (1 << TWIE) | (1 << TWEN);
+}
+
+uint8_t isTWIReady()
+{
+ if ( (TWIInfo.mode == Ready) | (TWIInfo.mode == RepeatedStartSent) )
+ {
+
+// xprintf("i2c ready\n");
+ return 1;
+ }
+ else
+ {
+ if(TWIInfo.mode == Initializing){
+ switch(TWIInfo.errorCode){
+ case TWI_SUCCESS:
+ break;
+ case TWI_NO_RELEVANT_INFO:
+
+ break;
+ case TWI_LOST_ARBIT:
+ case TWI_MT_DATA_NACK:
+ // Some kind of I2C error, reset and re-init
+ xprintf("I2C init error: %d\n", TWIInfo.errorCode);
+ TWCR = (1 << TWINT)|(1 << TWSTO);
+ TWIInit();
+ break;
+ default:
+ xprintf("Other i2c init error: %d\n", TWIInfo.errorCode);
+ }
+ }
+ return 0;
+ }
+}
+
+
+void TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart, uint8_t blocking)
+{
+ // Wait until ready
+ while (!isTWIReady()) {_delay_us(1);}
+ // Reset the I2C stuff
+ TWCR = (1 << TWINT)|(1 << TWSTO);
+ TWIInit();
+ // Set repeated start mode
+ TWIInfo.repStart = repStart;
+ // Copy transmit info to global variables
+ TWITransmitBuffer = (uint8_t *)TXdata;
+ TXBuffLen = dataLen;
+ TXBuffIndex = 0;
+
+ // If a repeated start has been sent, then devices are already listening for an address
+ // and another start does not need to be sent.
+ if (TWIInfo.mode == RepeatedStartSent)
+ {
+ TWIInfo.mode = Initializing;
+ TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer
+ TWISendTransmit(); // Send the data
+ }
+ else // Otherwise, just send the normal start signal to begin transmission.
+ {
+ TWIInfo.mode = Initializing;
+ TWISendStart();
+ }
+ if(blocking){
+ // Wait until ready
+ while (!isTWIReady()){_delay_us(1);}
+ }
+}
+
+
+// uint8_t TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart)
+// {
+// if (dataLen <= TXMAXBUFLEN)
+// {
+// // Wait until ready
+// while (!isTWIReady()) {_delay_us(1);}
+// // Set repeated start mode
+// TWIInfo.repStart = repStart;
+// // Copy data into the transmit buffer
+// uint8_t *data = (uint8_t *)TXdata;
+// for (int i = 0; i < dataLen; i++)
+// {
+// TWITransmitBuffer[i] = data[i];
+// }
+// // Copy transmit info to global variables
+// TXBuffLen = dataLen;
+// TXBuffIndex = 0;
+
+// // If a repeated start has been sent, then devices are already listening for an address
+// // and another start does not need to be sent.
+// if (TWIInfo.mode == RepeatedStartSent)
+// {
+// TWIInfo.mode = Initializing;
+// TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer
+// TWISendTransmit(); // Send the data
+// }
+// else // Otherwise, just send the normal start signal to begin transmission.
+// {
+// TWIInfo.mode = Initializing;
+// TWISendStart();
+// }
+
+// }
+// else
+// {
+// return 1; // return an error if data length is longer than buffer
+// }
+// return 0;
+// }
+
+uint8_t TWIReadData(uint8_t TWIaddr, uint8_t bytesToRead, uint8_t repStart)
+{
+ // Check if number of bytes to read can fit in the RXbuffer
+ if (bytesToRead < RXMAXBUFLEN)
+ {
+ // Reset buffer index and set RXBuffLen to the number of bytes to read
+ RXBuffIndex = 0;
+ RXBuffLen = bytesToRead;
+ // Create the one value array for the address to be transmitted
+ uint8_t TXdata[1];
+ // Shift the address and AND a 1 into the read write bit (set to write mode)
+ TXdata[0] = (TWIaddr << 1) | 0x01;
+ // Use the TWITransmitData function to initialize the transfer and address the slave
+ TWITransmitData(TXdata, 1, repStart, 0);
+ }
+ else
+ {
+ return 0;
+ }
+ return 1;
+}
+
+ISR (TWI_vect)
+{
+ switch (TWI_STATUS)
+ {
+ // ----\/ ---- MASTER TRANSMITTER OR WRITING ADDRESS ----\/ ---- //
+ case TWI_MT_SLAW_ACK: // SLA+W transmitted and ACK received
+ // Set mode to Master Transmitter
+ TWIInfo.mode = MasterTransmitter;
+ case TWI_START_SENT: // Start condition has been transmitted
+ case TWI_MT_DATA_ACK: // Data byte has been transmitted, ACK received
+ if (TXBuffIndex < TXBuffLen) // If there is more data to send
+ {
+ TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer
+ TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
+ TWISendTransmit(); // Send the data
+ }
+ // This transmission is complete however do not release bus yet
+ else if (TWIInfo.repStart)
+ {
+ TWIInfo.errorCode = 0xFF;
+ TWISendStart();
+ }
+ // All transmissions are complete, exit
+ else
+ {
+ TWIInfo.mode = Ready;
+ TWIInfo.errorCode = 0xFF;
+ TWISendStop();
+ }
+ break;
+
+ // ----\/ ---- MASTER RECEIVER ----\/ ---- //
+
+ case TWI_MR_SLAR_ACK: // SLA+R has been transmitted, ACK has been received
+ // Switch to Master Receiver mode
+ TWIInfo.mode = MasterReceiver;
+ // If there is more than one byte to be read, receive data byte and return an ACK
+ if (RXBuffIndex < RXBuffLen-1)
+ {
+ TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
+ TWISendACK();
+ }
+ // Otherwise when a data byte (the only data byte) is received, return NACK
+ else
+ {
+ TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
+ TWISendNACK();
+ }
+ break;
+
+ case TWI_MR_DATA_ACK: // Data has been received, ACK has been transmitted.
+
+ /// -- HANDLE DATA BYTE --- ///
+ TWIReceiveBuffer[RXBuffIndex++] = TWDR;
+ // If there is more than one byte to be read, receive data byte and return an ACK
+ if (RXBuffIndex < RXBuffLen-1)
+ {
+ TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
+ TWISendACK();
+ }
+ // Otherwise when a data byte (the only data byte) is received, return NACK
+ else
+ {
+ TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
+ TWISendNACK();
+ }
+ break;
+
+ case TWI_MR_DATA_NACK: // Data byte has been received, NACK has been transmitted. End of transmission.
+
+ /// -- HANDLE DATA BYTE --- ///
+ TWIReceiveBuffer[RXBuffIndex++] = TWDR;
+ // This transmission is complete however do not release bus yet
+ if (TWIInfo.repStart)
+ {
+ TWIInfo.errorCode = 0xFF;
+ TWISendStart();
+ }
+ // All transmissions are complete, exit
+ else
+ {
+ TWIInfo.mode = Ready;
+ TWIInfo.errorCode = 0xFF;
+ TWISendStop();
+ }
+ break;
+
+ // ----\/ ---- MT and MR common ----\/ ---- //
+
+ case TWI_MR_SLAR_NACK: // SLA+R transmitted, NACK received
+ case TWI_MT_SLAW_NACK: // SLA+W transmitted, NACK received
+ case TWI_MT_DATA_NACK: // Data byte has been transmitted, NACK received
+ case TWI_LOST_ARBIT: // Arbitration has been lost
+ // Return error and send stop and set mode to ready
+ if (TWIInfo.repStart)
+ {
+ TWIInfo.errorCode = TWI_STATUS;
+ TWISendStart();
+ }
+ // All transmissions are complete, exit
+ else
+ {
+ TWIInfo.mode = Ready;
+ TWIInfo.errorCode = TWI_STATUS;
+ TWISendStop();
+ }
+ break;
+ case TWI_REP_START_SENT: // Repeated start has been transmitted
+ // Set the mode but DO NOT clear TWINT as the next data is not yet ready
+ TWIInfo.mode = RepeatedStartSent;
+ break;
+
+ // ----\/ ---- SLAVE RECEIVER ----\/ ---- //
+
+ // TODO IMPLEMENT SLAVE RECEIVER FUNCTIONALITY
+
+ // ----\/ ---- SLAVE TRANSMITTER ----\/ ---- //
+
+ // TODO IMPLEMENT SLAVE TRANSMITTER FUNCTIONALITY
+
+ // ----\/ ---- MISCELLANEOUS STATES ----\/ ---- //
+ case TWI_NO_RELEVANT_INFO: // It is not really possible to get into this ISR on this condition
+ // Rather, it is there to be manually set between operations
+ break;
+ case TWI_ILLEGAL_START_STOP: // Illegal START/STOP, abort and return error
+ TWIInfo.errorCode = TWI_ILLEGAL_START_STOP;
+ TWIInfo.mode = Ready;
+ TWISendStop();
+ break;
+ }
+
+}
diff --git a/keyboards/woodkeys/meira/TWIlib.h b/keyboards/woodkeys/meira/TWIlib.h
new file mode 100755
index 0000000000..8ba261c6e5
--- /dev/null
+++ b/keyboards/woodkeys/meira/TWIlib.h
@@ -0,0 +1,71 @@
+/*
+ * TWIlib.h
+ *
+ * Created: 6/01/2014 10:38:42 PM
+ * Author: Chris Herring
+ */
+
+
+#ifndef TWILIB_H_
+#define TWILIB_H_
+// TWI bit rate
+#define TWI_FREQ 400000
+// Get TWI status
+#define TWI_STATUS (TWSR & 0xF8)
+// Transmit buffer length
+#define TXMAXBUFLEN 20
+// Receive buffer length
+#define RXMAXBUFLEN 20
+
+typedef enum {
+ Ready,
+ Initializing,
+ RepeatedStartSent,
+ MasterTransmitter,
+ MasterReceiver,
+ SlaceTransmitter,
+ SlaveReciever
+ } TWIMode;
+
+ typedef struct TWIInfoStruct{
+ TWIMode mode;
+ uint8_t errorCode;
+ uint8_t repStart;
+ }TWIInfoStruct;
+
+extern TWIInfoStruct TWIInfo;
+
+// TWI Status Codes
+#define TWI_START_SENT 0x08 // Start sent
+#define TWI_REP_START_SENT 0x10 // Repeated Start sent
+// Master Transmitter Mode
+#define TWI_MT_SLAW_ACK 0x18 // SLA+W sent and ACK received
+#define TWI_MT_SLAW_NACK 0x20 // SLA+W sent and NACK received
+#define TWI_MT_DATA_ACK 0x28 // DATA sent and ACK received
+#define TWI_MT_DATA_NACK 0x30 // DATA sent and NACK received
+// Master Receiver Mode
+#define TWI_MR_SLAR_ACK 0x40 // SLA+R sent, ACK received
+#define TWI_MR_SLAR_NACK 0x48 // SLA+R sent, NACK received
+#define TWI_MR_DATA_ACK 0x50 // Data received, ACK returned
+#define TWI_MR_DATA_NACK 0x58 // Data received, NACK returned
+
+// Miscellaneous States
+#define TWI_LOST_ARBIT 0x38 // Arbitration has been lost
+#define TWI_NO_RELEVANT_INFO 0xF8 // No relevant information available
+#define TWI_ILLEGAL_START_STOP 0x00 // Illegal START or STOP condition has been detected
+#define TWI_SUCCESS 0xFF // Successful transfer, this state is impossible from TWSR as bit2 is 0 and read only
+
+
+#define TWISendStart() (TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE)) // Send the START signal, enable interrupts and TWI, clear TWINT flag to resume transfer.
+#define TWISendStop() (TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)) // Send the STOP signal, enable interrupts and TWI, clear TWINT flag.
+#define TWISendTransmit() (TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE)) // Used to resume a transfer, clear TWINT and ensure that TWI and interrupts are enabled.
+#define TWISendACK() (TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA)) // FOR MR mode. Resume a transfer, ensure that TWI and interrupts are enabled and respond with an ACK if the device is addressed as a slave or after it receives a byte.
+#define TWISendNACK() (TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE)) // FOR MR mode. Resume a transfer, ensure that TWI and interrupts are enabled but DO NOT respond with an ACK if the device is addressed as a slave or after it receives a byte.
+
+// Function declarations
+void TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart, uint8_t blocking);
+void TWIInit(void);
+uint8_t TWIReadData(uint8_t TWIaddr, uint8_t bytesToRead, uint8_t repStart);
+uint8_t isTWIReady(void);
+
+#endif // TWICOMMS_H_ \ No newline at end of file
diff --git a/keyboards/woodkeys/meira/config.h b/keyboards/woodkeys/meira/config.h
new file mode 100644
index 0000000000..999ab1bf8a
--- /dev/null
+++ b/keyboards/woodkeys/meira/config.h
@@ -0,0 +1,45 @@
+/*
+Copyright 2017 Cole Markham
+
+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/>.
+*/
+
+#pragma once
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6061
+#define DEVICE_VER 0x0001
+#define MANUFACTURER WoodKeys.click
+#define PRODUCT Meira
+
+/* key matrix size */
+#define MATRIX_ROWS 4
+#define MATRIX_COLS 12
+
+/* COL2ROW, ROW2COL*/
+//#define DIODE_DIRECTION
+
+#ifdef BACKLIGHT_ENABLE
+#define BACKLIGHT_LEVELS 10
+#define BACKLIGHT_PWM_MAP {2, 4, 8, 16, 40, 55, 70, 128, 200, 255}
+#endif
+
+#ifdef RGBLIGHT_ENABLE
+#define RGB_DI_PIN D3
+
+#define RGBLED_NUM 15 // Number of LEDs
+#endif
diff --git a/keyboards/woodkeys/meira/featherble/config.h b/keyboards/woodkeys/meira/featherble/config.h
new file mode 100644
index 0000000000..94bef3b330
--- /dev/null
+++ b/keyboards/woodkeys/meira/featherble/config.h
@@ -0,0 +1,97 @@
+/*
+Copyright 2017 Cole Markham, WoodKeys.click
+
+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/>.
+*/
+
+#pragma once
+
+#include "config_common.h"
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { F7, F6, F5, F4 }
+// Column pins to demux in LSB order
+#define MATRIX_COL_PINS { C7, B7, B6, C6, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN }
+#define MATRIX_COL_PINS_SCANNED { C7, B7, B6, C6 }
+#define LED_EN_PIN D2
+#define UNUSED_PINS
+
+#define QMK_SPEAKER B5
+#define AUDIO_PIN B5
+#define AUDIO_VOICES
+
+// #define BACKLIGHT_PIN B7
+// #define BACKLIGHT_BREATHING
+//#define BACKLIGHT_LEVELS 3
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCE 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+
+/* 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
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+//#define FORCE_NKRO
+
+/*
+ * 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
diff --git a/keyboards/woodkeys/meira/featherble/featherble.c b/keyboards/woodkeys/meira/featherble/featherble.c
new file mode 100644
index 0000000000..63ade21904
--- /dev/null
+++ b/keyboards/woodkeys/meira/featherble/featherble.c
@@ -0,0 +1,17 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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 "meira.h"
diff --git a/keyboards/woodkeys/meira/featherble/featherble.h b/keyboards/woodkeys/meira/featherble/featherble.h
new file mode 100644
index 0000000000..eab7c639b9
--- /dev/null
+++ b/keyboards/woodkeys/meira/featherble/featherble.h
@@ -0,0 +1,19 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "meira.h"
diff --git a/keyboards/woodkeys/meira/featherble/rules.mk b/keyboards/woodkeys/meira/featherble/rules.mk
new file mode 100644
index 0000000000..01f1af1ae8
--- /dev/null
+++ b/keyboards/woodkeys/meira/featherble/rules.mk
@@ -0,0 +1,5 @@
+# Processor frequency
+F_CPU = 8000000
+
+BLUETOOTH_ENABLE = yes
+BLUETOOTH_DRIVER = BluefruitLE
diff --git a/keyboards/woodkeys/meira/info.json b/keyboards/woodkeys/meira/info.json
new file mode 100644
index 0000000000..de9ce42f8e
--- /dev/null
+++ b/keyboards/woodkeys/meira/info.json
@@ -0,0 +1,65 @@
+{
+ "keyboard_name": "Meira",
+ "url": "",
+ "maintainer": "colemarkham",
+ "layout_aliases": {
+ "LAYOUT": "LAYOUT_ortho_4x12"
+ },
+ "layouts": {
+ "LAYOUT_ortho_4x12": {
+ "layout": [
+ {"x":0, "y":0},
+ {"x":1, "y":0},
+ {"x":2, "y":0},
+ {"x":3, "y":0},
+ {"x":4, "y":0},
+ {"x":5, "y":0},
+ {"x":6, "y":0},
+ {"x":7, "y":0},
+ {"x":8, "y":0},
+ {"x":9, "y":0},
+ {"x":10, "y":0},
+ {"x":11, "y":0},
+
+ {"x":0, "y":1},
+ {"x":1, "y":1},
+ {"x":2, "y":1},
+ {"x":3, "y":1},
+ {"x":4, "y":1},
+ {"x":5, "y":1},
+ {"x":6, "y":1},
+ {"x":7, "y":1},
+ {"x":8, "y":1},
+ {"x":9, "y":1},
+ {"x":10, "y":1},
+ {"x":11, "y":1},
+
+ {"x":0, "y":2},
+ {"x":1, "y":2},
+ {"x":2, "y":2},
+ {"x":3, "y":2},
+ {"x":4, "y":2},
+ {"x":5, "y":2},
+ {"x":6, "y":2},
+ {"x":7, "y":2},
+ {"x":8, "y":2},
+ {"x":9, "y":2},
+ {"x":10, "y":2},
+ {"x":11, "y":2},
+
+ {"x":0, "y":3},
+ {"x":1, "y":3},
+ {"x":2, "y":3},
+ {"x":3, "y":3},
+ {"x":4, "y":3},
+ {"x":5, "y":3},
+ {"x":6, "y":3},
+ {"x":7, "y":3},
+ {"x":8, "y":3},
+ {"x":9, "y":3},
+ {"x":10, "y":3},
+ {"x":11, "y":3}
+ ]
+ }
+ }
+}
diff --git a/keyboards/woodkeys/meira/issi.c b/keyboards/woodkeys/meira/issi.c
new file mode 100755
index 0000000000..600a465ba3
--- /dev/null
+++ b/keyboards/woodkeys/meira/issi.c
@@ -0,0 +1,286 @@
+#ifdef ISSI_ENABLE
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <util/delay.h>
+#include <avr/sfr_defs.h>
+#include <avr/io.h>
+#include <util/twi.h>
+#include "issi.h"
+#include "print.h"
+#include "TWIlib.h"
+
+#define ISSI_ADDR_DEFAULT 0xE8
+
+#define ISSI_REG_CONFIG 0x00
+#define ISSI_REG_CONFIG_PICTUREMODE 0x00
+#define ISSI_REG_CONFIG_AUTOPLAYMODE 0x08
+
+#define ISSI_CONF_PICTUREMODE 0x00
+#define ISSI_CONF_AUTOFRAMEMODE 0x04
+#define ISSI_CONF_AUDIOMODE 0x08
+
+#define ISSI_REG_PICTUREFRAME 0x01
+
+#define ISSI_REG_SHUTDOWN 0x0A
+#define ISSI_REG_AUDIOSYNC 0x06
+
+#define ISSI_COMMANDREGISTER 0xFD
+#define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine'
+uint8_t control[8][9] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+ISSIDeviceStruct *issi_devices[4] = {0, 0, 0, 0};
+
+#ifndef cbi
+#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+#endif
+
+#ifndef sbi
+#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
+#endif
+
+#define I2C_WRITE 0
+#define F_SCL 400000UL // SCL frequency
+#define Prescaler 1
+#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)
+
+uint8_t i2c_start(uint8_t address)
+{
+ // reset TWI control register
+ TWCR = 0;
+ // transmit START condition
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+ // wait for end of transmission
+ while( !(TWCR & (1<<TWINT)) );
+
+ // check if the start condition was successfully transmitted
+ if((TWSR & 0xF8) != TW_START){ return 1; }
+
+ // load slave address into data register
+ TWDR = address;
+ // start transmission of address
+ TWCR = (1<<TWINT) | (1<<TWEN);
+ // wait for end of transmission
+ while( !(TWCR & (1<<TWINT)) );
+
+ // check if the device has acknowledged the READ / WRITE mode
+ uint8_t twst = TW_STATUS & 0xF8;
+ if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
+
+ return 0;
+}
+
+uint8_t i2c_write(uint8_t data)
+{
+ // load data into data register
+ TWDR = data;
+ // start transmission of data
+ TWCR = (1 << TWINT) | (1 << TWEN);
+ // wait for end of transmission
+ while (!(TWCR & (1 << TWINT)))
+ ;
+
+ if ((TWSR & 0xF8) != TW_MT_DATA_ACK) {
+ return 1;
+ }
+ return 0;
+}
+
+uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length)
+{
+ TWBR = (uint8_t)TWBR_val;
+ if (i2c_start(address | I2C_WRITE))
+ return 1;
+ for (uint16_t i = 0; i < length; i++) {
+ if (i2c_write(data[i]))
+ return 1;
+ }
+ // transmit STOP condition
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
+ return 0;
+}
+
+void setFrame(uint8_t device, uint8_t frame)
+{
+ static uint8_t current_frame = -1;
+ if(current_frame != frame){
+ uint8_t payload[] = {
+ ISSI_ADDR_DEFAULT | device << 1,
+ ISSI_COMMANDREGISTER,
+ frame
+ };
+ TWITransmitData(payload, sizeof(payload), 0, 1);
+ }
+ // static uint8_t current_frame = 0xFF;
+ // if(current_frame == frame){
+ // // return;
+ // }
+ // uint8_t payload[2] = { ISSI_COMMANDREGISTER, frame };
+ // i2c_transmit(ISSI_ADDR_DEFAULT | device << 1, payload, 2);
+ // current_frame = frame;
+}
+
+void writeRegister8(uint8_t device, uint8_t frame, uint8_t reg, uint8_t data)
+{
+ // Set the frame
+ setFrame(device, frame);
+
+ // Write to the register
+ uint8_t payload[] = {
+ ISSI_ADDR_DEFAULT | device << 1,
+ reg,
+ data
+ };
+ TWITransmitData(payload, sizeof(payload), 0, 1);
+}
+
+// void activateLED(uint8_t matrix, uint8_t cx, uint8_t cy, uint8_t pwm)
+// {
+// xprintf("activeLED: %02X %02X %02X %02X\n", matrix, cy, cx, pwm);
+// uint8_t x = cx - 1; // funciton takes 1 based counts, but we need 0...
+// uint8_t y = cy - 1; // creating them once for less confusion
+// if(pwm == 0){
+// cbi(control[matrix][y], x);
+// }else{
+// sbi(control[matrix][y], x);
+// }
+// uint8_t device = (matrix & 0x06) >> 1;
+// uint8_t control_reg = (y << 1) | (matrix & 0x01);
+// uint8_t pwm_reg = 0;
+// switch(matrix & 0x01){
+// case 0:
+// pwm_reg = 0x24;
+// break;
+// case 1:
+// pwm_reg = 0x2C;
+// break;
+// }
+// pwm_reg += (y << 4) + x;
+// xprintf(" device: %02X\n", device);
+// xprintf(" control: %02X %02X\n", control_reg, control[matrix][y]);
+// xprintf(" pwm: %02X %02X\n", pwm_reg, pwm);
+// writeRegister8(device, 0, control_reg, control[matrix][y]);
+// writeRegister8(device, 0, control_reg + 0x12, control[matrix][y]);
+// writeRegister8(device, 0, pwm_reg, pwm);
+// }
+
+void activateLED(uint8_t matrix, uint8_t cx, uint8_t cy, uint8_t pwm)
+{
+ uint8_t device_addr = (matrix & 0x06) >> 1;
+ ISSIDeviceStruct *device = issi_devices[device_addr];
+ if(device == 0){
+ return;
+ }
+ // xprintf("activeLED: %02X %02X %02X %02X\n", matrix, cy, cx, pwm);
+ uint8_t x = cx - 1; // funciton takes 1 based counts, but we need 0...
+ uint8_t y = cy - 1; // creating them once for less confusion
+ uint8_t control_reg = (y << 1) | (matrix & 0x01);
+ if(pwm == 0){
+ cbi(device->led_ctrl[control_reg], x);
+ cbi(device->led_blink_ctrl[control_reg], x);
+ }else{
+ sbi(device->led_ctrl[control_reg], x);
+ sbi(device->led_blink_ctrl[control_reg], x);
+ }
+ uint8_t pwm_reg = 0;
+ switch(matrix & 0x01){
+ case 0:
+ pwm_reg = 0x00;
+ break;
+ case 1:
+ pwm_reg = 0x08;
+ break;
+ }
+ pwm_reg += (y << 4) + x;
+ // xprintf(" device_addr: %02X\n", device_addr);
+ // xprintf(" control: %02X %02X\n", control_reg, control[matrix][y]);
+ // xprintf(" pwm: %02X %02X\n", pwm_reg, pwm);
+ // writeRegister8(device_addr, 0, control_reg, control[matrix][y]);
+ device->led_pwm[pwm_reg] = pwm;
+ device->led_dirty = 1;
+
+ // writeRegister8(device_addr, 0, control_reg + 0x12, control[matrix][y]);
+ // writeRegister8(device_addr, 0, pwm_reg, pwm);
+}
+
+void update_issi(uint8_t device_addr, uint8_t blocking)
+{
+ // This seems to take about 6ms
+ ISSIDeviceStruct *device = issi_devices[device_addr];
+ if(device != 0){
+ if(device->fn_dirty){
+ device->fn_dirty = 0;
+ setFrame(device_addr, ISSI_BANK_FUNCTIONREG);
+ TWITransmitData(&device->fn_device_addr, sizeof(device->fn_registers) + 2, 0, 1);
+ }
+ if(device->led_dirty){
+ device->led_dirty = 0;
+ setFrame(device_addr, 0);
+ TWITransmitData(&device->led_device_addr, 0xB6, 0, blocking);
+ }
+ }
+}
+
+void issi_init(void)
+{
+ // Set LED_EN/SDB high to enable the chip
+ xprintf("Enabing SDB on pin: %d\n", LED_EN_PIN);
+ _SFR_IO8((LED_EN_PIN >> 4) + 1) &= ~_BV(LED_EN_PIN & 0xF); // IN
+ _SFR_IO8((LED_EN_PIN >> 4) + 2) |= _BV(LED_EN_PIN & 0xF); // HI
+ TWIInit();
+ for(uint8_t device_addr = 0; device_addr < 4; device_addr++){
+ xprintf("ISSI Init device: %d\n", device_addr);
+ // If this device has been previously allocated, free it
+ if(issi_devices[device_addr] != 0){
+ free(issi_devices[device_addr]);
+ }
+ // Try to shutdown the device, if this fails skip this device
+ writeRegister8(device_addr, ISSI_BANK_FUNCTIONREG, ISSI_REG_SHUTDOWN, 0x00);
+ while (!isTWIReady()){_delay_us(1);}
+ if(TWIInfo.errorCode != 0xFF){
+ xprintf("ISSI init failed %d %02X %02X\n", device_addr, TWIInfo.mode, TWIInfo.errorCode);
+ continue;
+ }
+ // Allocate the device structure - calloc zeros it for us
+ ISSIDeviceStruct *device = (ISSIDeviceStruct *)calloc(sizeof(ISSIDeviceStruct) * 2, 1);
+ issi_devices[device_addr] = device;
+ device->fn_device_addr = ISSI_ADDR_DEFAULT | device_addr << 1;
+ device->fn_register_addr = 0;
+ device->led_device_addr = ISSI_ADDR_DEFAULT | device_addr << 1;
+ device->led_register_addr = 0;
+ // set dirty bits so that all of the buffered data is written out
+ device->fn_dirty = 1;
+ device->led_dirty = 1;
+ update_issi(device_addr, 1);
+ // Set the function register to picture mode
+ // device->fn_reg[ISSI_REG_CONFIG] = ISSI_REG_CONFIG_PICTUREMODE;
+ writeRegister8(device_addr, ISSI_BANK_FUNCTIONREG, ISSI_REG_SHUTDOWN, 0x01);
+ }
+
+ // Shutdown and set all registers to 0
+ // writeRegister8(device_addr, ISSI_BANK_FUNCTIONREG, ISSI_REG_SHUTDOWN, 0x00);
+ // for(uint8_t bank = 0; bank <= 7; bank++){
+ // for (uint8_t reg = 0x00; reg <= 0xB3; reg++) {
+ // writeRegister8(device_addr, bank, reg, 0x00);
+ // }
+ // }
+ // for (uint8_t reg = 0; reg <= 0x0C; reg++) {
+ // writeRegister8(device_addr, ISSI_BANK_FUNCTIONREG, reg, 0x00);
+ // }
+ // writeRegister8(device_addr, ISSI_BANK_FUNCTIONREG, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE);
+ // writeRegister8(device_addr, ISSI_BANK_FUNCTIONREG, ISSI_REG_SHUTDOWN, 0x01);
+ // picture mode
+ // writeRegister8(ISSI_BANK_FUNCTIONREG, 0x01, 0x01);
+
+ //Enable blink
+ // writeRegister8(ISSI_BANK_FUNCTIONREG, 0x05, 0x48B);
+
+ //Enable Breath
+
+}
+
+#endif
diff --git a/keyboards/woodkeys/meira/issi.h b/keyboards/woodkeys/meira/issi.h
new file mode 100755
index 0000000000..74379ddbc8
--- /dev/null
+++ b/keyboards/woodkeys/meira/issi.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#ifdef ISSI_ENABLE
+
+typedef struct ISSIDeviceStruct{
+ uint8_t fn_dirty; // function registers need to be resent
+ uint8_t fn_device_addr;
+ uint8_t fn_register_addr;
+ uint8_t fn_registers[13];
+ uint8_t led_dirty; // LED data has changed and needs to be resent
+ uint8_t led_device_addr;
+ uint8_t led_register_addr;
+ uint8_t led_ctrl[18];
+ uint8_t led_blink_ctrl[18];
+ uint8_t led_pwm[144];
+}ISSIDeviceStruct;
+
+extern ISSIDeviceStruct *issi_devices[];
+
+// Low level commands- 'device' is the 2-bit i2c id.
+void issi_init(void);
+void set_shutdown(uint8_t device, uint8_t shutdown);
+void writeRegister8(uint8_t device, uint8_t frame, uint8_t reg, uint8_t data);
+
+// Higher level, no device is given, but it is calculated from 'matrix'
+// Each device has 2 blocks, max of 4 devices:
+// Device | Block = Matrix
+// 0 A 0
+// 0 B 1
+// 1 A 2
+// 1 B 3
+// 2 A 4
+// 2 B 5
+// 3 A 6
+// 3 B 7
+void activateLED(uint8_t matrix, uint8_t cx, uint8_t cy, uint8_t pwm);
+void update_issi(uint8_t device_addr, uint8_t blocking);
+
+#endif
diff --git a/keyboards/woodkeys/meira/keymaps/cole/config.h b/keyboards/woodkeys/meira/keymaps/cole/config.h
new file mode 100644
index 0000000000..90c490e836
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/cole/config.h
@@ -0,0 +1,31 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+// place overrides here
+#define MUSIC_MASK (keycode != KC_NO)
+#ifdef AUDIO_ENABLE
+ #define STARTUP_SONG SONG(IMPERIAL_MARCH)
+ // Disable music mode to keep the firmware size down
+ #define NO_MUSIC_MODE
+
+#endif
+
+#endif
diff --git a/keyboards/woodkeys/meira/keymaps/cole/keymap.c b/keyboards/woodkeys/meira/keymaps/cole/keymap.c
new file mode 100644
index 0000000000..94806c5da2
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/cole/keymap.c
@@ -0,0 +1,225 @@
+/* Copyright 2017 Cole Markham
+ *
+ * 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 "meira.h"
+#include "lighting.h"
+
+#ifdef RGBLIGHT_ENABLE
+//Following line allows macro to read current RGB settings
+extern rgblight_config_t rgblight_config;
+#endif
+
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _ADJUST 16
+
+
+#ifndef BLUETOOTH_ENABLE
+#define OUT_BT KC_TRNS
+#endif
+
+enum custom_keycodes {
+ QWERTY = SAFE_RANGE,
+ LOWER,
+ RAISE,
+ ADJUST,
+};
+
+// define variables for reactive RGB
+bool TOG_STATUS = false;
+int RGB_current_mode;
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Esc | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Tab | A | S | D | F | G | H | J | K | L | ; | ' |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Adjust| Ctrl | Ctrl | Alt |Lower | Cmd |Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_QWERTY] = LAYOUT( \
+ KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \
+ KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, \
+ ADJUST, KC_LCTL, KC_LALT, KC_LALT, LOWER, KC_LGUI, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \
+ ),
+
+ /* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | ~ | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | | \ | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_LOWER] = LAYOUT( \
+ _______, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL, \
+ KC_TILD, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, \
+ _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, KC_QUOT, \
+ _______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END \
+ ),
+
+ /* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | ` | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Home | PgUp | PgDn | End |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_RAISE] = LAYOUT( \
+ _______, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, \
+ _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END \
+ ),
+
+ /* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * | | Reset| | | | | | | | | | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak| | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | | | | | | | | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_ADJUST] = LAYOUT( \
+ RESET, _______, _______, KC_MRWD, KC_MPLY, KC_MFFD, KC_PSCR, _______, KC_MUTE, KC_VOLD, KC_VOLU, KC_DEL, \
+ BL_STEP, RGB_MOD, _______, AU_ON, AU_OFF, _______, _______, _______, _______, _______, _______, _______, \
+ BL_TOGG, RGB_TOG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, KC_PSCR, _______, _______, _______, _______, _______, _______, _______, OUT_AUTO, OUT_USB, OUT_BT \
+ )
+};
+
+// Setting ADJUST layer RGB back to default
+void update_tri_layer_RGB(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+ if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode);
+#endif
+ layer_on(layer3);
+ } else {
+ layer_off(layer3);
+ }
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case LOWER:
+ if (record->event.pressed) {
+ //not sure how to have keyboard check mode and set it to a variable, so my work around
+ //uses another variable that would be set to true after the first time a reactive key is pressed.
+ if (TOG_STATUS) { //TOG_STATUS checks is another reactive key currently pressed, only changes RGB mode if returns false
+ } else {
+ TOG_STATUS = !TOG_STATUS;
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(16);
+#endif
+ }
+ layer_on(_LOWER);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ } else {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode); // revert RGB to initial mode prior to RGB mode change
+#endif
+ TOG_STATUS = false;
+ layer_off(_LOWER);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case RAISE:
+ if (record->event.pressed) {
+ //not sure how to have keyboard check mode and set it to a variable, so my work around
+ //uses another variable that would be set to true after the first time a reactive key is pressed.
+ if (TOG_STATUS) { //TOG_STATUS checks is another reactive key currently pressed, only changes RGB mode if returns false
+ } else {
+ TOG_STATUS = !TOG_STATUS;
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(15);
+#endif
+ }
+ layer_on(_RAISE);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ } else {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode); // revert RGB to initial mode prior to RGB mode change
+#endif
+ layer_off(_RAISE);
+ TOG_STATUS = false;
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case ADJUST:
+ // FIXME add RGB feedback
+ if (record->event.pressed) {
+ layer_on(_ADJUST);
+ } else {
+ layer_off(_ADJUST);
+ }
+ return false;
+ break;
+ case BL_TOGG:
+#ifdef BACKLIGHT_ENABLE
+ if (record->event.pressed) {
+ print("Enabling backlight\n");
+ backlight_init_ports();
+ }
+#endif
+ return false;
+ break;
+ case BL_STEP:
+ if (record->event.pressed) {
+#ifdef BACKLIGHT_ENABLE
+ backlight_step();
+#endif
+
+ }
+ return false;
+ break;
+ //led operations - RGB mode change now updates the RGB_current_mode to allow the right RGB mode to be set after reactive keys are released
+#ifdef RGBLIGHT_ENABLE
+ case RGB_MOD:
+ if (record->event.pressed) {
+ rgblight_mode(RGB_current_mode);
+ rgblight_step();
+ RGB_current_mode = rgblight_config.mode;
+ }
+ return false;
+ break;
+#endif
+ }
+ return true;
+}
+
+void led_set_user(uint8_t usb_led) {
+
+}
diff --git a/keyboards/woodkeys/meira/keymaps/cole/readme.md b/keyboards/woodkeys/meira/keymaps/cole/readme.md
new file mode 100644
index 0000000000..be84048813
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/cole/readme.md
@@ -0,0 +1 @@
+# The default keymap for meira
diff --git a/keyboards/woodkeys/meira/keymaps/cole/rules.mk b/keyboards/woodkeys/meira/keymaps/cole/rules.mk
new file mode 100644
index 0000000000..eed6b9c119
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/cole/rules.mk
@@ -0,0 +1,2 @@
+AUDIO_ENABLE = yes # Audio output on port C6
+LTO_ENABLE = yes # -4-7k
diff --git a/keyboards/woodkeys/meira/keymaps/default/config.h b/keyboards/woodkeys/meira/keymaps/default/config.h
new file mode 100644
index 0000000000..e3776d2eff
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/default/config.h
@@ -0,0 +1,31 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+// place overrides here
+
+// place overrides here
+#define MUSIC_MASK (keycode != KC_NO)
+#ifdef AUDIO_ENABLE
+ #define STARTUP_SONG SONG(PLANCK_SOUND)
+ // #define STARTUP_SONG SONG(NO_SOUND)
+
+ #define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \
+ SONG(COLEMAK_SOUND), \
+ SONG(DVORAK_SOUND) \
+ }
+#endif
diff --git a/keyboards/woodkeys/meira/keymaps/default/keymap.c b/keyboards/woodkeys/meira/keymaps/default/keymap.c
new file mode 100644
index 0000000000..dacf848cf1
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/default/keymap.c
@@ -0,0 +1,299 @@
+/* Copyright 2017 Cole Markham
+ *
+ * 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 QMK_KEYBOARD_H
+#include "lighting.h"
+
+#ifdef RGBLIGHT_ENABLE
+// Following line allows macro to read current RGB settings
+extern rgblight_config_t rgblight_config;
+#endif
+
+enum layer_names {
+ _QWERTY,
+ _COLEMAK,
+ _DVORAK,
+ _LOWER,
+ _RAISE,
+ _ADJUST
+};
+
+enum custom_keycodes {
+ QWERTY = SAFE_RANGE,
+ COLEMAK,
+ DVORAK,
+ LOWER,
+ RAISE,
+ ADJUST
+};
+
+#ifdef AUDIO_ENABLE
+
+float tone_my_startup[][2] = SONG(ODE_TO_JOY);
+float tone_my_goodbye[][2] = SONG(ROCK_A_BYE_BABY);
+
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+
+#endif /* AUDIO_ENABLE */
+
+// define variables for reactive RGB
+bool TOG_STATUS = false;
+int RGB_current_mode;
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Esc | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Tab | A | S | D | F | G | H | J | K | L | ; | ' |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Adjust| Ctrl | Alt | Alt |Lower | Cmd |Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_QWERTY] = LAYOUT(
+ KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,
+ KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT,
+ ADJUST, KC_LCTL, KC_LALT, KC_LALT, LOWER, KC_LGUI, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT
+ ),
+
+ /* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | R | S | T | D | H | N | E | I | O | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_COLEMAK] = LAYOUT(
+ KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC,
+ KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT,
+ ADJUST, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT
+ ),
+
+ /* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | " | , | . | P | Y | F | G | C | R | L | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | O | E | U | I | D | H | T | N | S | / |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_DVORAK] = LAYOUT(
+ KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC,
+ KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH,
+ KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT,
+ ADJUST, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT
+ ),
+
+ /* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | ~ | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | | \ | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_LOWER] = LAYOUT(
+ _______, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL,
+ KC_TILD, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE,
+ _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, S(KC_NUHS), S(KC_NUBS), _______, _______, KC_QUOT,
+ _______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END
+ ),
+
+ /* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | ` | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | Home | PgUp | PgDn | End |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_RAISE] = LAYOUT(
+ _______, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS,
+ _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END
+ ),
+
+ /* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * | | Reset| | | | | | | | | | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak| | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | | | | | | | | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_ADJUST] = LAYOUT(
+ BL_TOGG, RESET, _______, KC_MRWD, KC_MPLY, KC_MFFD, KC_PSCR, _______, KC_MUTE, KC_VOLD, KC_VOLU, KC_DEL,
+ BL_STEP, RGB_MOD, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, KC_PSCR, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+ )
+};
+
+// Setting ADJUST layer RGB back to default
+void update_tri_layer_RGB(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+ if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode);
+#endif
+ layer_on(layer3);
+ } else {
+ layer_off(layer3);
+ }
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QWERTY:
+ if (record->event.pressed) {
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_qwerty);
+#endif
+ // persistent_default_layer_set(1UL<<_QWERTY);
+ }
+ return false;
+ break;
+ case COLEMAK:
+ if (record->event.pressed) {
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_colemak);
+#endif
+ // persistent_default_layer_set(1UL<<_COLEMAK);
+ }
+ return false;
+ break;
+ case DVORAK:
+ if (record->event.pressed) {
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_dvorak);
+#endif
+ // persistent_default_layer_set(1UL<<_DVORAK);
+ }
+ return false;
+ break;
+ case LOWER:
+ if (record->event.pressed) {
+ // not sure how to have keyboard check mode and set it to a variable, so my work around
+ // uses another variable that would be set to true after the first time a reactive key is pressed.
+ if (TOG_STATUS) { // TOG_STATUS checks is another reactive key currently pressed, only changes RGB mode if returns false
+ } else {
+ TOG_STATUS = !TOG_STATUS;
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(16);
+#endif
+ }
+ layer_on(_LOWER);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ } else {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode); // revert RGB to initial mode prior to RGB mode change
+#endif
+ TOG_STATUS = false;
+ layer_off(_LOWER);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case RAISE:
+ if (record->event.pressed) {
+ // not sure how to have keyboard check mode and set it to a variable, so my work around
+ // uses another variable that would be set to true after the first time a reactive key is pressed.
+ if (TOG_STATUS) { // TOG_STATUS checks is another reactive key currently pressed, only changes RGB mode if returns false
+ } else {
+ TOG_STATUS = !TOG_STATUS;
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(15);
+#endif
+ }
+ layer_on(_RAISE);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ } else {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode); // revert RGB to initial mode prior to RGB mode change
+#endif
+ layer_off(_RAISE);
+ TOG_STATUS = false;
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case ADJUST:
+ // FIXME add RGB feedback
+ if (record->event.pressed) {
+ layer_on(_ADJUST);
+ } else {
+ layer_off(_ADJUST);
+ }
+ return false;
+ break;
+ case BL_TOGG:
+#ifdef BACKLIGHT_ENABLE
+ if (record->event.pressed) {
+ print("Enabling backlight\n");
+ backlight_init_ports();
+ }
+#endif
+ return false;
+ break;
+ case BL_STEP:
+ if (record->event.pressed) {
+ print("Stepping backlight\n");
+#ifdef BACKLIGHT_ENABLE
+ print("Really stepping backlight\n");
+ backlight_step();
+#endif
+ }
+ return false;
+ break;
+ // led operations - RGB mode change now updates the RGB_current_mode to allow the right RGB mode to be set after reactive keys are released
+#ifdef RGBLIGHT_ENABLE
+ case RGB_MOD:
+ if (record->event.pressed) {
+ rgblight_mode(RGB_current_mode);
+ rgblight_step();
+ RGB_current_mode = rgblight_config.mode;
+ }
+ return false;
+ break;
+#endif
+ // case BL_INC:
+ // meira_inc_backlight_level();
+ // return false;
+ // break;
+ }
+ return true;
+}
diff --git a/keyboards/woodkeys/meira/keymaps/default/readme.md b/keyboards/woodkeys/meira/keymaps/default/readme.md
new file mode 100644
index 0000000000..be84048813
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/default/readme.md
@@ -0,0 +1 @@
+# The default keymap for meira
diff --git a/keyboards/woodkeys/meira/keymaps/grahampheath/config.h b/keyboards/woodkeys/meira/keymaps/grahampheath/config.h
new file mode 100644
index 0000000000..604f378461
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/grahampheath/config.h
@@ -0,0 +1,35 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+// place overrides here
+#define MUSIC_MASK (keycode != KC_NO)
+#define AUDIO_PIN C6
+#ifdef AUDIO_ENABLE
+ #define STARTUP_SONG SONG(PLANCK_SOUND)
+ // #define STARTUP_SONG SONG(NO_SOUND)
+
+ #define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \
+ SONG(COLEMAK_SOUND), \
+ SONG(DVORAK_SOUND) \
+ }
+#endif
+
+#endif
diff --git a/keyboards/woodkeys/meira/keymaps/grahampheath/keymap.c b/keyboards/woodkeys/meira/keymaps/grahampheath/keymap.c
new file mode 100644
index 0000000000..35fa31b8b8
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/grahampheath/keymap.c
@@ -0,0 +1,398 @@
+/* Copyright 2017 Cole Markham
+ *
+ * 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 "meira.h"
+#include "action_layer.h"
+#include "action_code.h"
+
+#ifdef RGBLIGHT_ENABLE
+//Following line allows macro to read current RGB settings
+extern rgblight_config_t rgblight_config;
+#endif
+
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _EMOJI 5
+#define _ADJUST 16
+
+enum custom_keycodes {
+ QWERTY = SAFE_RANGE,
+ COLEMAK,
+ DVORAK,
+ LOWER,
+ RAISE,
+ EMOJI,
+ ADJUST,
+ TOUNGE,
+ JOY,
+ FROWN,
+ HEART,
+ THMBUP,
+ THMBDN,
+ SHRUG,
+ WINK,
+ GRIN,
+ LLAP,
+ CRY,
+ SHIT,
+ FLIP,
+ FNGLEFT,
+ ABOVE,
+ FNGRIGHT,
+ CONFUSED
+};
+
+// define variables for reactive RGB
+bool TOG_STATUS = false;
+int RGB_current_mode;
+
+#define KC_X0 MT(MOD_LCTL, KC_ESC) // Hold for Left Ctrl, Tap for GraveESC
+#define KC_X1 MT(MOD_RSFT, KC_ENT) // Hold for Right Shift, Tap for Enter
+#define KC_X2 MT(MOD_RSFT, LGUI(KC_ENT)) // Send Command Enter
+#define KC_X3 MT(MOD_LGUI, KC_SPC) // Hold for Left GUI, Tap for Space
+#define KC_EMOJ TT(_EMOJI) // Hold for Emoji Layer, or tap 5 times.
+#define KC_QS LGUI(KC_SPC) // Send Command + Space (for QuickSilver).
+#define KC_TABR LGUI(KC_RCBR) // Send Command + } (for tab changing).
+#define KC_TABL LGUI(KC_LCBR) // Send Command + { (for tab changing).
+#define HYPR_0 HYPR(KC_TILD) // Send Hyper + ~.
+#define HYPR_1 HYPR(KC_EXLM) // Send Hyper + !.
+#define HYPR_2 HYPR(KC_AT) // Send Hyper + @.
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Esc | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Tab | A | S | D | F | G | H | J | K | L | ; | ' |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Emoji | Ctrl | Alt |Lower | Cmd |Space+|Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_QWERTY] = LAYOUT( \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \
+ KC_X0, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_X1, \
+ KC_EMOJ, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_X3, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \
+ ),
+
+ /* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | R | S | T | D | H | N | E | I | O | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_COLEMAK] = LAYOUT( \
+ KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC, \
+ KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT , \
+ ADJUST, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \
+ ),
+
+ /* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | " | , | . | P | Y | F | G | C | R | L | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | O | E | U | I | D | H | T | N | S | / |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_DVORAK] = LAYOUT( \
+ KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC, \
+ KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH, \
+ KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT , \
+ ADJUST, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \
+ ),
+
+ /* Emoji Layer
+ *
+ * ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
+ * │HYPR0│ │ ;-) │ │ │ :-P │ │ │:'-( │FLIP │ │ │
+ * ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
+ * │HYPR1│ 👆 │SHRUG│ │ :-( │ │ <3 │ :-) │ │LLAP │ │ │
+ * ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
+ * │HYPR2│ │ │ | :-\ │ │ │ :-D │ SHIT│ │ │ │
+ * ├─────┼─────┼─────┼─────┼─────┼─────┴─────┼─────┼─────┼─────┼─────┼─────┤
+ * │ │ │ │ │Brig-│ Sleep │Brig+│ 👈 │ 👎 | 👍 │ 👉 │
+ * └─────┴─────┴─────┴─────┴─────┴───────────┴─────┴─────┴─────┴─────┴─────┘
+ */
+ [_EMOJI] = LAYOUT ( \
+ HYPR_0, _______, WINK, _______, _______, TOUNGE, _______, _______, CRY, FLIP, _______, _______, \
+ HYPR_1, ABOVE, SHRUG, _______, FROWN, _______, HEART, JOY, _______, LLAP, _______, _______, \
+ HYPR_2, _______, _______, _______, CONFUSED, _______, _______, GRIN, SHIT, _______, _______, _______, \
+ _______, _______, _______, _______, KC_SLCK, KC_SLEP, KC_SLEP, KC_PAUS, FNGLEFT, THMBDN, THMBUP, FNGRIGHT \
+ ),
+
+
+
+ /* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Tab- | | | Tab+ |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_LOWER] = LAYOUT( \
+ KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC, \
+ KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, \
+ KC_LSFT, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______, \
+ _______, _______, _______, _______, _______, KC_QS, KC_QS, _______, KC_TABL, _______, _______, KC_TABR \
+ ),
+
+ /* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | ` | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Home | PgUp | PgDn | End |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_RAISE] = LAYOUT( \
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, \
+ KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, \
+ KC_LSFT, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, KC_X2, \
+ _______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END \
+ ),
+
+ /* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * | | Reset| | | | | | | | | | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak| | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | | | | | | | | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_ADJUST] = LAYOUT( \
+ _______, RESET, _______, _______, _______, _______, KC_PSCR, _______, _______, _______, _______, KC_DEL, \
+ _______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
+ )
+};
+
+#ifdef AUDIO_ENABLE
+
+ float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+ float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+ float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+
+
+ float plover_song[][2] = SONG(PLOVER_SOUND);
+ float plover_gb_song[][2] = SONG(PLOVER_GOODBYE_SOUND);
+#endif
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QWERTY:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_qwerty);
+ #endif
+ }
+ return false;
+ break;
+ case COLEMAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_colemak);
+ #endif
+ }
+ return false;
+ break;
+ case DVORAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_dvorak);
+ #endif
+ }
+ return false;
+ break;
+ case LOWER:
+ if (record->event.pressed) {
+ layer_on(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case RAISE:
+ if (record->event.pressed) {
+ layer_on(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case ADJUST:
+ // FIXME add RGB feedback
+ if (record->event.pressed) {
+ layer_on(_ADJUST);
+ } else {
+ layer_off(_ADJUST);
+ }
+ return false;
+ break;
+ case BL_TOGG:
+#ifdef ISSI_ENABLE
+ if (record->event.pressed) {
+ print("Enabling backlight\n");
+ issi_init();
+ }
+#endif
+ return false;
+ break;
+ case BL_STEP:
+ if (record->event.pressed) {
+ print("Stepping backlight\n");
+
+ }
+ return false;
+ break;
+ case FLIP:
+ if (record->event.pressed) {
+ SEND_STRING("&fliptable;");
+ }
+ return false;
+ break;
+ case CONFUSED:
+ if (record->event.pressed) {
+ SEND_STRING(":-\\");
+ }
+ // register_codeturn false;
+ break;
+ case SHIT:
+ if (record->event.pressed) {
+ SEND_STRING("&shit; ");
+ }
+ return false;
+ break;
+ case CRY:
+ if (record->event.pressed) {
+ SEND_STRING(":'-( ");
+ }
+ return false;
+ break;
+ case LLAP:
+ if (record->event.pressed) {
+ SEND_STRING("&llap; ");
+ }
+ return false;
+ break;
+ case GRIN:
+ if (record->event.pressed) {
+ SEND_STRING(":-D ");
+ }
+ return false;
+ break;
+ case TOUNGE:
+ if (record->event.pressed) {
+ SEND_STRING(":-P ");
+ }
+ return false;
+ break;
+ case JOY:
+ if (record->event.pressed) {
+ SEND_STRING(":-) ");
+ }
+ return false;
+ break;
+ case FROWN:
+ if (record->event.pressed) {
+ SEND_STRING(":-( ");
+ }
+ return false;
+ break;
+ case HEART:
+ if (record->event.pressed) {
+ SEND_STRING("<3 ");
+ }
+ return false;
+ break;
+ case SHRUG:
+ if (record->event.pressed) {
+ SEND_STRING("&shrug; ");
+ }
+ return false;
+ break;
+ case THMBUP:
+ if (record->event.pressed) {
+ SEND_STRING("&thumbup; ");
+ }
+ return false;
+ break;
+ case THMBDN:
+ if (record->event.pressed) {
+ SEND_STRING("&thumbdown; ");
+ }
+ return false;
+ break;
+ case FNGLEFT:
+ if (record->event.pressed) {
+ SEND_STRING("&fingerleft; ");
+ }
+ return false;
+ break;
+ case FNGRIGHT:
+ if (record->event.pressed) {
+ SEND_STRING("&fingerright; ");
+ }
+ return false;
+ break;
+ case WINK:
+ if (record->event.pressed) {
+ SEND_STRING(";-) ");
+ }
+ return false;
+ break;
+ case ABOVE:
+ if (record->event.pressed) {
+ SEND_STRING("&above; ");
+ }
+ return false;
+ break;
+
+ }
+ return true;
+}
+
+void led_set_user(uint8_t usb_led) {
+
+}
diff --git a/keyboards/woodkeys/meira/keymaps/grahampheath/readme.md b/keyboards/woodkeys/meira/keymaps/grahampheath/readme.md
new file mode 100644
index 0000000000..10459e3566
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/grahampheath/readme.md
@@ -0,0 +1,55 @@
+# Graham's Meira.
+
+Don't expect this to work for you unaltered! For the record, these are my notes, not a guide for you :-)
+
+## Known issues:
+Anything over 28k will begin to overwrite the boot loader, which is a pain!
+
+Be sure to check file size with:
+```
+avr-size meira_promicro_grahampheath.hex
+```
+
+## Sounds
+I've added a [8ohm 0.5W speaker](http://a.co/6MIKZSy), its a bit large, but it fits in approximately the same space as the ProMicro. I soldered directly to PC6 and GND.
+
+As the Meira code stood, adding sound increased the hex beyond what the boot loader could handle, so I had to dial way back on features that I wasnt using, like backlighting and RGB support. I also removed function keys, though I think you could restore some of these features, you certainly can't restore all of them and still fit with a boot loader.
+
+## Build
+
+Built for the ProMicro with:
+```
+make meira/promicro:grahampheath
+```
+
+Build and upload with, which is cool because it will sense your port.
+```
+make meira/promicro:grahampheath:avrdude
+```
+
+Program a hex directly with:
+```
+avrdude -p atmega32u4 -P /dev/tty.usbmodem14111 -c avr109 -v -e -D -U flash:w:meira_promicro_grahampheath.hex
+```
+
+If you use an AVRISP you will be program a hex without a boot loader:
+```
+avrdude -p atmega32u4 -P /dev/tty.usbmodem14111 -c avrisp -v -e -U flash:w:meira_promicro_grahampheath.hex
+```
+
+## Bricked
+Did you overwrite your boot loader?
+
+I did...
+
+I used an [Ardunio as an ISP](https://learn.sparkfun.com/tutorials/installing-an-arduino-bootloader), and was able to program various boot loaders. Ultimately it seemed like this was the right combo:
+
+[ProMicro pinout](https://cdn.sparkfun.com/assets/9/c/3/c/4/523a1765757b7f5c6e8b4567.png)
+
+[Wiring](https://forum.arduino.cc/index.php?PHPSESSID=467mm69btif69hdj5e3gil5465&action=dlattach;topic=363341.0;attach=145820): [via u/dmjlambert](https://forum.arduino.cc/index.php?topic=363341.0)
+
+ProMicro boot loader hex is called `Caterina-promicro16.hex` and is stored on [Sparkfun's GitHub](https://github.com/sparkfun/Arduino_Boards)
+
+```
+avrdude -c avrisp -p m32u4 -P /dev/tty.usbmodem14141 -v -e -U flash:w:Caterina-promicro16.hex -U efuse:w:0xcb:m -U hfuse:w:0xd8:m -U lfuse:w:0xff:m
+```
diff --git a/keyboards/woodkeys/meira/keymaps/grahampheath/rules.mk b/keyboards/woodkeys/meira/keymaps/grahampheath/rules.mk
new file mode 100644
index 0000000000..1c61fe1c12
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/grahampheath/rules.mk
@@ -0,0 +1,5 @@
+AUDIO_ENABLE = yes # Audio output on port C6
+LTO_ENABLE = yes # -4-7k
+MOUSEKEY_ENABLE = no # Mouse keys(-47kb)
+ISSI_ENABLE = no
+BACKLIGHT_ENABLE = no \ No newline at end of file
diff --git a/keyboards/woodkeys/meira/keymaps/takmiya/config.h b/keyboards/woodkeys/meira/keymaps/takmiya/config.h
new file mode 100644
index 0000000000..97210115b9
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/takmiya/config.h
@@ -0,0 +1,24 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+// place overrides here
+
+#endif
diff --git a/keyboards/woodkeys/meira/keymaps/takmiya/keymap.c b/keyboards/woodkeys/meira/keymaps/takmiya/keymap.c
new file mode 100644
index 0000000000..25f50abc49
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/takmiya/keymap.c
@@ -0,0 +1,234 @@
+/* Copyright 2017 Cole Markham
+ *
+ * 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 "meira.h"
+#include "issi.h"
+#include "lighting.h"
+
+#ifdef RGBLIGHT_ENABLE
+//Following line allows macro to read current RGB settings
+extern rgblight_config_t rgblight_config;
+#endif
+
+#define _QWERTY 0
+#define _LOWER 1
+#define _RAISE 2
+#define _ADJUST 16
+
+enum custom_keycodes {
+ QWERTY = SAFE_RANGE,
+ LOWER,
+ RAISE,
+ ADJUST,
+};
+
+// define variables for reactive RGB
+bool TOG_STATUS = false;
+int RGB_current_mode;
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | S | D | F | G | H | J | K | L | ; | ' |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . |//GUI |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | GUI | Alt | GUI |Lower |Space |Enter |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_QWERTY] = LAYOUT( \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \
+ KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, GUI_T(KC_SLSH), KC_ENT, \
+ KC_LCTL, KC_LGUI, KC_LALT, KC_RGUI, LOWER, KC_SPC, KC_ENT, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \
+ ),
+
+ /* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | DEL |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | Home | PgUp | PgDn | End |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_LOWER] = LAYOUT( \
+ KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL, \
+ _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, \
+ _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, S(KC_NUHS), S(KC_NUBS), _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END \
+ ),
+
+ /* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | DEL |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | Home | PgUp | PgDn | End |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_RAISE] = LAYOUT( \
+ KC_GRV , KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
+ _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, \
+ _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END \
+ ),
+
+ /* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * | | Reset| | | | | | | | | | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty| | | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | | | | | | | | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [_ADJUST] = LAYOUT( \
+ BL_TOGG, RESET, _______, KC_MRWD, KC_MPLY, KC_MFFD, KC_PSCR, _______, KC_MUTE, KC_VOLD, KC_VOLU, KC_DEL, \
+ BL_STEP, RGB_MOD, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, KC_PSCR, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
+ )
+};
+
+// Setting ADJUST layer RGB back to default
+void update_tri_layer_RGB(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+ if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode);
+#endif
+ layer_on(layer3);
+ } else {
+ layer_off(layer3);
+ }
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QWERTY:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_qwerty);
+ #endif
+// persistent_default_layer_set(1UL<<_QWERTY);
+ }
+ return false;
+ break;
+ case LOWER:
+ if (record->event.pressed) {
+ //not sure how to have keyboard check mode and set it to a variable, so my work around
+ //uses another variable that would be set to true after the first time a reactive key is pressed.
+ if (TOG_STATUS) { //TOG_STATUS checks is another reactive key currently pressed, only changes RGB mode if returns false
+ } else {
+ TOG_STATUS = !TOG_STATUS;
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(16);
+#endif
+ }
+ layer_on(_LOWER);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ } else {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode); // revert RGB to initial mode prior to RGB mode change
+#endif
+ TOG_STATUS = false;
+ layer_off(_LOWER);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case RAISE:
+ if (record->event.pressed) {
+ //not sure how to have keyboard check mode and set it to a variable, so my work around
+ //uses another variable that would be set to true after the first time a reactive key is pressed.
+ if (TOG_STATUS) { //TOG_STATUS checks is another reactive key currently pressed, only changes RGB mode if returns false
+ } else {
+ TOG_STATUS = !TOG_STATUS;
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(15);
+#endif
+ }
+ layer_on(_RAISE);
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ } else {
+#ifdef RGBLIGHT_ENABLE
+ rgblight_mode(RGB_current_mode); // revert RGB to initial mode prior to RGB mode change
+#endif
+ layer_off(_RAISE);
+ TOG_STATUS = false;
+ update_tri_layer_RGB(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case ADJUST:
+ // FIXME add RGB feedback
+ if (record->event.pressed) {
+ layer_on(_ADJUST);
+ } else {
+ layer_off(_ADJUST);
+ }
+ return false;
+ break;
+ case BL_TOGG:
+#ifdef ISSI_ENABLE
+ if (record->event.pressed) {
+ print("Enabling backlight\n");
+ issi_init();
+ }
+#endif
+ return false;
+ break;
+ case BL_STEP:
+ if (record->event.pressed) {
+ print("Stepping backlight\n");
+#ifdef BACKLIGHT_ENABLE
+ print("Really stepping backlight\n");
+ backlight_step();
+#endif
+
+ }
+ return false;
+ break;
+ //led operations - RGB mode change now updates the RGB_current_mode to allow the right RGB mode to be set after reactive keys are released
+#ifdef RGBLIGHT_ENABLE
+ case RGB_MOD:
+ if (record->event.pressed) {
+ rgblight_mode(RGB_current_mode);
+ rgblight_step();
+ RGB_current_mode = rgblight_config.mode;
+ }
+ return false;
+ break;
+#endif
+// case BL_INC:
+// meira_inc_backlight_level();
+// return false;
+// break;
+ }
+ return true;
+}
+
+void led_set_user(uint8_t usb_led) {
+
+}
diff --git a/keyboards/woodkeys/meira/keymaps/takmiya/readme.md b/keyboards/woodkeys/meira/keymaps/takmiya/readme.md
new file mode 100644
index 0000000000..40f48bb091
--- /dev/null
+++ b/keyboards/woodkeys/meira/keymaps/takmiya/readme.md
@@ -0,0 +1 @@
+# The takmiya keymap for meira
diff --git a/keyboards/woodkeys/meira/lighting.c b/keyboards/woodkeys/meira/lighting.c
new file mode 100755
index 0000000000..1a3c954bcf
--- /dev/null
+++ b/keyboards/woodkeys/meira/lighting.c
@@ -0,0 +1,97 @@
+#ifdef ISSI_ENABLE
+
+
+#include <avr/sfr_defs.h>
+#include <avr/timer_avr.h>
+#include <avr/wdt.h>
+#include "meira.h"
+#include "issi.h"
+#include "TWIlib.h"
+#include "lighting.h"
+#include "debug.h"
+#include "audio.h"
+
+
+const uint8_t backlight_pwm_map[BACKLIGHT_LEVELS] = BACKLIGHT_PWM_MAP;
+
+ const uint8_t switch_matrices[] = {0, 1};
+
+ // Maps switch LEDs from Row/Col to ISSI matrix.
+ // Value breakdown:
+ // Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ // | | ISSI Col | ISSI Row |
+ // / |
+ // Device
+// const uint8_t switch_leds[MATRIX_ROWS][MATRIX_COLS] =
+// LAYOUT(
+// 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5,
+// 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0xB9, 0xB8, 0xB7, 0xB6, 0xB5,
+// 0x49, 0x48, 0x47, 0x45, 0x44, 0x43, 0x42, 0x41, 0xC9, 0xC8, 0xC7, 0xC6,
+// 0x59, 0x58, 0x57, 0x56, 0x55, 0x51, 0xD6, 0xE5, 0xE4, 0xE3, 0xE2);
+
+void backlight_set(uint8_t level){
+#ifdef BACKLIGHT_ENABLE
+ uint8_t pwm_value = 0;
+ if(level >= BACKLIGHT_LEVELS){
+ level = BACKLIGHT_LEVELS;
+ }
+ if(level > 0){
+ pwm_value = backlight_pwm_map[level-1];
+ }
+ xprintf("BACKLIGHT_LEVELS: %d\n", BACKLIGHT_LEVELS);
+ xprintf("backlight_set level: %d pwm: %d\n", level, pwm_value);
+ for(int x = 1; x <= 9; x++){
+ for(int y = 1; y <= 9; y++){
+ activateLED(switch_matrices[0], x, y, pwm_value);
+ activateLED(switch_matrices[1], x, y, pwm_value);
+ }
+ }
+#endif
+}
+
+
+
+void set_backlight_by_keymap(uint8_t col, uint8_t row){
+// dprintf("LED: %02X, %d %d %d\n", lookup_value, matrix, led_col, led_row);
+// activateLED(matrix, led_col, led_row, 255);
+}
+
+void force_issi_refresh(){
+ issi_devices[0]->led_dirty = true;
+ update_issi(0, true);
+ issi_devices[3]->led_dirty = true;
+ update_issi(3, true);
+}
+
+void led_test(){
+#ifdef WATCHDOG_ENABLE
+ // This test take a long time to run, disable the WTD until its complete
+ wdt_disable();
+#endif
+ backlight_set(0);
+ force_issi_refresh();
+// for(uint8_t x = 0; x < sizeof(rgb_sequence); x++){
+// set_rgb(rgb_sequence[x], 255, 0, 0);
+// force_issi_refresh();
+// _delay_ms(250);
+// set_rgb(rgb_sequence[x], 0, 255, 0);
+// force_issi_refresh();
+// _delay_ms(250);
+// set_rgb(rgb_sequence[x], 0, 0, 255);
+// force_issi_refresh();
+// _delay_ms(250);
+// set_rgb(rgb_sequence[x], 0, 0, 0);
+// force_issi_refresh();
+// }
+#ifdef WATCHDOG_ENABLE
+ wdt_enable(WDTO_250MS);
+#endif
+}
+
+void backlight_init_ports(void){
+ xprintf("backlight_init_ports\n");
+ issi_init();
+}
+
+#endif
+
diff --git a/keyboards/woodkeys/meira/lighting.h b/keyboards/woodkeys/meira/lighting.h
new file mode 100755
index 0000000000..42fee8ac92
--- /dev/null
+++ b/keyboards/woodkeys/meira/lighting.h
@@ -0,0 +1,6 @@
+#pragma once
+
+void led_test(void);
+void force_issi_refresh(void);
+void set_backlight(uint8_t level);
+void set_backlight_by_keymap(uint8_t col, uint8_t row);
diff --git a/keyboards/woodkeys/meira/matrix.c b/keyboards/woodkeys/meira/matrix.c
new file mode 100644
index 0000000000..8e8e9485b4
--- /dev/null
+++ b/keyboards/woodkeys/meira/matrix.c
@@ -0,0 +1,270 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+Copyright 2017 Cole Markham <cole@ccmcomputing.net>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * scan matrix
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#if defined(__AVR__)
+#include <avr/io.h>
+#endif
+#include "meira.h"
+#include "wait.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "config.h"
+#include "timer.h"
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+
+#if (DEBOUNCE > 0)
+ static uint16_t debouncing_time;
+ static bool debouncing = false;
+#endif
+
+#if (MATRIX_COLS <= 8)
+# define print_matrix_header() print("\nr/c 01234567\n")
+# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop(matrix[i])
+# define ROW_SHIFTER ((uint8_t)1)
+#elif (MATRIX_COLS <= 16)
+# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
+# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop16(matrix[i])
+# define ROW_SHIFTER ((uint16_t)1)
+#elif (MATRIX_COLS <= 32)
+# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
+# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop32(matrix[i])
+# define ROW_SHIFTER ((uint32_t)1)
+#endif
+
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
+static const uint8_t col_pins[4] = MATRIX_COL_PINS_SCANNED;
+//static const uint8_t lrow_pins[MATRIX_ROWS] = LED_ROW_PINS;
+//static const uint8_t lcol_pins[4] = LED_COL_PINS;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+static void init_rows(void);
+//static void init_lcols(void);
+static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
+static void unselect_cols(void);
+static void select_col(uint8_t col);
+
+
+__attribute__ ((weak))
+void matrix_init_kb(void) {
+ matrix_init_user();
+}
+
+__attribute__ ((weak))
+void matrix_scan_kb(void) {
+ matrix_scan_user();
+}
+
+__attribute__ ((weak))
+void matrix_init_user(void) {
+}
+
+__attribute__ ((weak))
+void matrix_scan_user(void) {
+}
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+void matrix_init(void)
+{
+ debug_enable = true;
+ debug_matrix = true;
+ debug_mouse = true;
+ // initialize row and col
+ unselect_cols();
+ init_rows();
+// init_lcols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ matrix_init_quantum();
+
+}
+
+uint8_t _matrix_scan(void)
+{
+ // Set col, read rows
+ for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
+# if (DEBOUNCE > 0)
+ bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
+ if (matrix_changed) {
+ debouncing = true;
+ debouncing_time = timer_read();
+ }
+# else
+ read_rows_on_col(matrix, current_col);
+# endif
+
+ }
+
+# if (DEBOUNCE > 0)
+ if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCE)) {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ debouncing = false;
+ }
+# endif
+
+ return 1;
+}
+
+uint8_t matrix_scan(void)
+{
+ uint8_t ret = _matrix_scan();
+ matrix_scan_quantum();
+ return ret;
+}
+
+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++) {
+ print_hex8(row); print(": ");
+ print_bin_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_rows(void)
+{
+ for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
+ uint8_t pin = row_pins[x];
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ }
+}
+
+
+static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
+{
+ bool matrix_changed = false;
+
+ // Select col and wait for col selection to stabilize
+ select_col(current_col);
+ wait_us(30);
+
+ // For each row...
+ for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
+ {
+
+ // Store last value of row prior to reading
+ matrix_row_t last_row_value = current_matrix[row_index];
+
+ // Check row pin state
+ if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
+ {
+ // Pin LO, set col bit
+ current_matrix[row_index] |= (ROW_SHIFTER << current_col);
+ }
+ else
+ {
+ // Pin HI, clear col bit
+ current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
+ }
+
+ // Determine if the matrix changed state
+ if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
+ {
+ matrix_changed = true;
+ }
+ }
+
+ // Unselect col
+ unselect_cols();
+
+ return matrix_changed;
+}
+
+static void select_col(uint8_t col)
+{
+#ifdef FLIPPED_BOARD
+ col = MATRIX_COLS - col - 1;
+#endif
+ for(uint8_t x = 0; x < 4; x++) {
+ uint8_t pin = col_pins[x];
+ _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
+ if (((col >> x) & 0x1) == 1){
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HIGH
+ } else {
+ _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
+ }
+ }
+}
+
+static void unselect_cols(void)
+{
+ // FIXME This really needs to use the global enable on the decoder, because currently this sets the value to col1
+ for(uint8_t x = 0; x < 4; x++) {
+ uint8_t pin = col_pins[x];
+ _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
+ _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
+ }
+}
diff --git a/keyboards/woodkeys/meira/meira.c b/keyboards/woodkeys/meira/meira.c
new file mode 100644
index 0000000000..e900fd0dd6
--- /dev/null
+++ b/keyboards/woodkeys/meira/meira.c
@@ -0,0 +1,97 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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 "meira.h"
+#include "issi.h"
+#include "TWIlib.h"
+#include "lighting.h"
+#include "quantum.h"
+#define BACKLIGHT_BREATHING
+
+extern void backlight_set(uint8_t level);
+
+void matrix_init_kb(void)
+{
+ debug_enable=true;
+ print("meira matrix_init_kb\n");
+
+#ifdef ISSI_ENABLE
+ issi_init();
+#endif
+#ifdef BACKLIGHT_ENABLE
+ backlight_set(5);
+#endif
+#ifdef WATCHDOG_ENABLE
+ // This is done after turning the layer LED red, if we're caught in a loop
+ // we should get a flashing red light
+ wdt_enable(WDTO_500MS);
+#endif
+
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+ matrix_init_user();
+}
+
+void matrix_scan_kb(void)
+{
+#ifdef WATCHDOG_ENABLE
+ wdt_reset();
+#endif
+#ifdef ISSI_ENABLE
+ // switch/underglow lighting update
+ static uint32_t issi_device = 0;
+ static uint32_t twi_last_ready = 0;
+ if(twi_last_ready > 1000){
+ // Its been way too long since the last ISSI update, reset the I2C bus and start again
+ xprintf("TWI failed to recover, TWI re-init\n");
+ twi_last_ready = 0;
+ TWIInit();
+ force_issi_refresh();
+ }
+ if(isTWIReady()){
+ twi_last_ready = 0;
+ // If the i2c bus is available, kick off the issi update, alternate between devices
+ update_issi(issi_device, issi_device);
+ if(issi_device){
+ issi_device = 0;
+ }else{
+ issi_device = 3;
+ }
+ }else{
+ twi_last_ready++;
+ }
+#endif
+ matrix_scan_user();
+}
+
+bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
+ // Test code that turns on the switch led for the key that is pressed
+ // set_backlight_by_keymap(record->event.key.col, record->event.key.row);
+ if (keycode == RESET) {
+ reset_keyboard_kb();
+ } else {
+ }
+ return process_record_user(keycode, record);
+}
+
+void reset_keyboard_kb(){
+#ifdef WATCHDOG_ENABLE
+ MCUSR = 0;
+ wdt_disable();
+ wdt_reset();
+#endif
+ xprintf("programming!\n");
+ reset_keyboard();
+}
diff --git a/keyboards/woodkeys/meira/meira.h b/keyboards/woodkeys/meira/meira.h
new file mode 100644
index 0000000000..55fccf5de5
--- /dev/null
+++ b/keyboards/woodkeys/meira/meira.h
@@ -0,0 +1,37 @@
+/* Copyright 2017 Cole Markham
+ *
+ * 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/>.
+ */
+#pragma once
+
+#include "quantum.h"
+#include "issi.h"
+
+void reset_keyboard_kb(void);
+
+// This a shortcut to help you visually see your layout.
+// The first section contains all of the arguments
+// The second converts the arguments into a two-dimensional array
+#define LAYOUT_ortho_4x12( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b \
+) \
+{ \
+ { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b }, \
+ { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b }, \
+ { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b }, \
+ { k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b } \
+}
diff --git a/keyboards/woodkeys/meira/promicro/config.h b/keyboards/woodkeys/meira/promicro/config.h
new file mode 100644
index 0000000000..bbdaa9dbd8
--- /dev/null
+++ b/keyboards/woodkeys/meira/promicro/config.h
@@ -0,0 +1,88 @@
+/*
+Copyright 2017 Cole Markham, WoodKeys.click
+
+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/>.
+*/
+
+#pragma once
+
+#include "config_common.h"
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { F7, F6, F5, F4 }
+// Column pins to demux in LSB order
+#define MATRIX_COL_PINS { B1, B3, B2, B6, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN }
+#define MATRIX_COL_PINS_SCANNED { B1, B3, B2, B6 }
+
+#define LED_EN_PIN D2
+#define UNUSED_PINS
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCE 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* 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
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+//#define FORCE_NKRO
+
+/*
+ * 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
diff --git a/keyboards/woodkeys/meira/promicro/promicro.c b/keyboards/woodkeys/meira/promicro/promicro.c
new file mode 100644
index 0000000000..63ade21904
--- /dev/null
+++ b/keyboards/woodkeys/meira/promicro/promicro.c
@@ -0,0 +1,17 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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 "meira.h"
diff --git a/keyboards/woodkeys/meira/promicro/promicro.h b/keyboards/woodkeys/meira/promicro/promicro.h
new file mode 100644
index 0000000000..eab7c639b9
--- /dev/null
+++ b/keyboards/woodkeys/meira/promicro/promicro.h
@@ -0,0 +1,19 @@
+/* Copyright 2017 Cole Markham, WoodKeys.click
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "meira.h"
diff --git a/keyboards/woodkeys/meira/promicro/rules.mk b/keyboards/woodkeys/meira/promicro/rules.mk
new file mode 100644
index 0000000000..09057bea54
--- /dev/null
+++ b/keyboards/woodkeys/meira/promicro/rules.mk
@@ -0,0 +1,3 @@
+# Disable unsupported hardware
+RGBLIGHT_SUPPORTED = no
+AUDIO_SUPPORTED = no
diff --git a/keyboards/woodkeys/meira/readme.md b/keyboards/woodkeys/meira/readme.md
new file mode 100644
index 0000000000..f0fb02b69e
--- /dev/null
+++ b/keyboards/woodkeys/meira/readme.md
@@ -0,0 +1,28 @@
+# Meira
+
+![Meira](https://i.imgur.com/kF4MFlWh.jpeg)
+
+A 4x12 ortholinear low-profile keyboard.
+
+* Keyboard Maintainer: [Cole Markham](https://github.com/colemarkham)
+* Hardware Supported: Meira/ProMicro, Meira/FeatherBLE
+* Hardware Availability: [WoodKeys.click](https://woodkeys.click/meira)
+
+Two controllers are supported: the Pro Micro, and the Adafruit Feather BLE 32u4. Support for each is defined as a hardware revision subfolder in QMK. Main differences include processor frequencies and matrix pinouts.
+
+Make examples for this keyboard (after setting up your build environment):
+
+ make woodkeys/meira/featherble:default # for Feather BLE 32u4 controllers
+ make woodkeys/meira/promicro:default # for Pro Micro controllers
+
+See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
+
+Both the Pro Micro and the Feather BLE use the Caterina bootloader, which is typically programmed using avrdude.
+
+## Matrix
+
+In order to have enough pins for the matrix and other functions, a custom matrix is implemented using a demultiplexer to scan the columns. Since the demux is active low, the diodes must be oriented with the cathode connected to the demux pin. When looking at the bottom of the board with the controller at the top right, the cathode mark on the diode should be toward the left.
+
+## LED Controller
+
+The in-switch LEDs are driven by an ISSI LED controller (IS31FL3731). The micro controller communicates with this chip using I2C. Individual LED control is possible, but currently only general backlighting support is implemented. This functionality is located in lighting.c, issi.c, and TWILib.c.
diff --git a/keyboards/woodkeys/meira/rules.mk b/keyboards/woodkeys/meira/rules.mk
new file mode 100644
index 0000000000..6b5025500c
--- /dev/null
+++ b/keyboards/woodkeys/meira/rules.mk
@@ -0,0 +1,34 @@
+# MCU name
+MCU = atmega32u4
+
+# Bootloader selection
+BOOTLOADER = caterina
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
+MOUSEKEY_ENABLE = no # Mouse keys
+EXTRAKEY_ENABLE = yes # Audio control and System control
+CONSOLE_ENABLE = no # Console for debug
+COMMAND_ENABLE = no # Commands for debug and configuration
+NKRO_ENABLE = no # Enable N-Key Rollover
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality, also set ISSI_ENABLE below for Meira
+BACKLIGHT_DRIVER = custom
+ISSI_ENABLE = yes # If the I2C pullup resistors aren't install this must be disabled
+RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
+AUDIO_ENABLE = no # Audio output
+
+CUSTOM_MATRIX = yes
+
+#ifeq ($(strip $(ISSI_ENABLE)), yes)
+# TMK_COMMON_DEFS += -DISSI_ENABLE
+#endif
+
+#ifeq ($(strip $(WATCHDOG_ENABLE)), yes)
+# TMK_COMMON_DEFS += -DWATCHDOG_ENABLE
+#endif
+SRC += matrix.c TWIlib.c issi.c lighting.c
+
+DEFAULT_FOLDER = woodkeys/meira/promicro
+LAYOUTS = ortho_4x12