summaryrefslogtreecommitdiffstats
path: root/keyboards/meira
diff options
context:
space:
mode:
authorCole Markham <github@ccmcomputing.net>2017-11-17 19:01:21 +0100
committerJack Humbert <jack.humb@gmail.com>2017-12-09 06:05:35 +0100
commita9a46adba0e005f6fecfb5ed47fe8a5eec4b06f4 (patch)
tree4dac82993f8ced6e3c7791b6d55a97c84122634b /keyboards/meira
parentc51dfef958bce4a792b66db337d5c7cdf0956fc4 (diff)
downloadqmk_firmware-a9a46adba0e005f6fecfb5ed47fe8a5eec4b06f4.tar.gz
qmk_firmware-a9a46adba0e005f6fecfb5ed47fe8a5eec4b06f4.tar.xz
Add support for Meira
Diffstat (limited to 'keyboards/meira')
-rwxr-xr-xkeyboards/meira/TWIlib.c287
-rwxr-xr-xkeyboards/meira/TWIlib.h81
-rw-r--r--keyboards/meira/config.h53
-rw-r--r--keyboards/meira/featherble/config.h175
-rw-r--r--keyboards/meira/featherble/featherble.c1
-rw-r--r--keyboards/meira/featherble/featherble.h9
-rw-r--r--keyboards/meira/featherble/rules.mk4
-rwxr-xr-xkeyboards/meira/issi.c286
-rwxr-xr-xkeyboards/meira/issi.h40
-rw-r--r--keyboards/meira/keymaps/default/config.h24
-rw-r--r--keyboards/meira/keymaps/default/keymap.c320
-rw-r--r--keyboards/meira/keymaps/default/readme.md1
-rwxr-xr-xkeyboards/meira/lighting.c95
-rwxr-xr-xkeyboards/meira/lighting.h9
-rw-r--r--keyboards/meira/matrix.c314
-rw-r--r--keyboards/meira/meira.c145
-rw-r--r--keyboards/meira/meira.h48
-rw-r--r--keyboards/meira/promicro/config.h168
-rw-r--r--keyboards/meira/promicro/promicro.c2
-rw-r--r--keyboards/meira/promicro/promicro.h10
-rw-r--r--keyboards/meira/promicro/rules.mk2
-rw-r--r--keyboards/meira/readme.md28
-rw-r--r--keyboards/meira/rules.mk84
23 files changed, 2186 insertions, 0 deletions
diff --git a/keyboards/meira/TWIlib.c b/keyboards/meira/TWIlib.c
new file mode 100755
index 000000000..8e0c97438
--- /dev/null
+++ b/keyboards/meira/TWIlib.c
@@ -0,0 +1,287 @@
+/*
+ * 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"
+
+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/meira/TWIlib.h b/keyboards/meira/TWIlib.h
new file mode 100755
index 000000000..6db3cc951
--- /dev/null
+++ b/keyboards/meira/TWIlib.h
@@ -0,0 +1,81 @@
+/*
+ * 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
+// 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)
+
+typedef enum {
+ Ready,
+ Initializing,
+ RepeatedStartSent,
+ MasterTransmitter,
+ MasterReceiver,
+ SlaceTransmitter,
+ SlaveReciever
+ } TWIMode;
+
+ typedef struct TWIInfoStruct{
+ TWIMode mode;
+ uint8_t errorCode;
+ uint8_t repStart;
+ }TWIInfoStruct;
+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/meira/config.h b/keyboards/meira/config.h
new file mode 100644
index 000000000..e335db90f
--- /dev/null
+++ b/keyboards/meira/config.h
@@ -0,0 +1,53 @@
+/*
+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/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#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
+#define DESCRIPTION Low-profile Ortholinear Compact keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 4
+#define MATRIX_COLS 12
+
+/* COL2ROW, ROW2COL, or CUSTOM_MATRIX */
+#define DIODE_DIRECTION CUSTOM_MATRIX
+
+#define BACKLIGHT_LEVELS 10
+#define BACKLIGHT_PWM_MAP {2, 4, 8, 16, 40, 55, 70, 128, 200, 255}
+#define BACKLIGHT_BREATHING
+
+#define RGB_DI_PIN D3
+#define RGBLIGHT_TIMER
+#define RGBLED_NUM 15 // Number of LEDs
+
+#ifdef SUBPROJECT_promicro
+ #include "promicro/config.h"
+#endif
+#ifdef SUBPROJECT_featherble
+ #include "featherble/config.h"
+#endif
+
+#endif
diff --git a/keyboards/meira/featherble/config.h b/keyboards/meira/featherble/config.h
new file mode 100644
index 000000000..ade3b2d57
--- /dev/null
+++ b/keyboards/meira/featherble/config.h
@@ -0,0 +1,175 @@
+/*
+Copyright 2017 REPLACE_WITH_YOUR_NAME
+
+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 FEATHERBLECONFIG_H
+#define FEATHERBLECONFIG_H
+
+#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 }
+#define LED_EN_PIN D2
+#define UNUSED_PINS
+
+#define CATERINA_BOOTLOADER
+
+
+// #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 DEBOUNCING_DELAY 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
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * 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
+
+/*
+ * MIDI options
+ */
+
+/* Prevent use of disabled MIDI features in the keymap */
+//#define MIDI_ENABLE_STRICT 1
+
+/* enable basic MIDI features:
+ - MIDI notes can be sent when in Music mode is on
+*/
+//#define MIDI_BASIC
+
+/* enable advanced MIDI features:
+ - MIDI notes can be added to the keymap
+ - Octave shift and transpose
+ - Virtual sustain, portamento, and modulation wheel
+ - etc.
+*/
+//#define MIDI_ADVANCED
+
+/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
+//#define MIDI_TONE_KEYCODE_OCTAVES 1
+
+#endif
diff --git a/keyboards/meira/featherble/featherble.c b/keyboards/meira/featherble/featherble.c
new file mode 100644
index 000000000..560f0db29
--- /dev/null
+++ b/keyboards/meira/featherble/featherble.c
@@ -0,0 +1 @@
+#include "meira.h"
diff --git a/keyboards/meira/featherble/featherble.h b/keyboards/meira/featherble/featherble.h
new file mode 100644
index 000000000..b7599b994
--- /dev/null
+++ b/keyboards/meira/featherble/featherble.h
@@ -0,0 +1,9 @@
+#ifndef FEATHERBLE_H
+#define FEATHERBLE_H
+
+#include "../meira.h"
+
+#include "quantum.h"
+
+
+#endif
diff --git a/keyboards/meira/featherble/rules.mk b/keyboards/meira/featherble/rules.mk
new file mode 100644
index 000000000..47d0e5b89
--- /dev/null
+++ b/keyboards/meira/featherble/rules.mk
@@ -0,0 +1,4 @@
+BLUETOOTH_ENABLE = yes
+BACKLIGHT_ENABLE = yes
+F_CPU = 8000000
+
diff --git a/keyboards/meira/issi.c b/keyboards/meira/issi.c
new file mode 100755
index 000000000..600a465ba
--- /dev/null
+++ b/keyboards/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/meira/issi.h b/keyboards/meira/issi.h
new file mode 100755
index 000000000..51777f6ee
--- /dev/null
+++ b/keyboards/meira/issi.h
@@ -0,0 +1,40 @@
+#ifdef ISSI_ENABLE
+#ifndef ISSI_H
+#define ISSI_H
+
+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
+#endif \ No newline at end of file
diff --git a/keyboards/meira/keymaps/default/config.h b/keyboards/meira/keymaps/default/config.h
new file mode 100644
index 000000000..f52a97bbc
--- /dev/null
+++ b/keyboards/meira/keymaps/default/config.h
@@ -0,0 +1,24 @@
+/* Copyright 2017 REPLACE_WITH_YOUR_NAME
+ *
+ * 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/meira/keymaps/default/keymap.c b/keyboards/meira/keymaps/default/keymap.c
new file mode 100644
index 000000000..acde30afc
--- /dev/null
+++ b/keyboards/meira/keymaps/default/keymap.c
@@ -0,0 +1,320 @@
+/* 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 _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _ADJUST 16
+
+enum custom_keycodes {
+ QWERTY = SAFE_RANGE,
+ COLEMAK,
+ DVORAK,
+ 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] = KEYMAP( \
+ 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] = KEYMAP( \
+ 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] = KEYMAP( \
+ 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] = KEYMAP( \
+ _______, 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] = KEYMAP( \
+ _______, 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] = KEYMAP( \
+ 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, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
+ )
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+// 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);
+ }
+}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+
+void matrix_init_user(void) {
+
+}
+
+void matrix_scan_user(void) {
+
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QWERTY:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
+ #endif
+// persistent_default_layer_set(1UL<<_QWERTY);
+ }
+ return false;
+ break;
+ case COLEMAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_colemak, false, 0);
+ #endif
+// persistent_default_layer_set(1UL<<_COLEMAK);
+ }
+ return false;
+ break;
+ case DVORAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
+ #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 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/meira/keymaps/default/readme.md b/keyboards/meira/keymaps/default/readme.md
new file mode 100644
index 000000000..be8404881
--- /dev/null
+++ b/keyboards/meira/keymaps/default/readme.md
@@ -0,0 +1 @@
+# The default keymap for meira
diff --git a/keyboards/meira/lighting.c b/keyboards/meira/lighting.c
new file mode 100755
index 000000000..fee70a32b
--- /dev/null
+++ b/keyboards/meira/lighting.c
@@ -0,0 +1,95 @@
+#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/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] =
+// KEYMAP(
+// 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/meira/lighting.h b/keyboards/meira/lighting.h
new file mode 100755
index 000000000..dc55b70ef
--- /dev/null
+++ b/keyboards/meira/lighting.h
@@ -0,0 +1,9 @@
+#ifndef LIGHTING_H
+#define LIGHTING_H
+
+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);
+
+#endif
diff --git a/keyboards/meira/matrix.c b/keyboards/meira/matrix.c
new file mode 100644
index 000000000..a4d8ec247
--- /dev/null
+++ b/keyboards/meira/matrix.c
@@ -0,0 +1,314 @@
+/*
+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 DEBOUNCING_DELAY
+# define DEBOUNCING_DELAY 5
+#endif
+
+#if (DEBOUNCING_DELAY > 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;
+//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_quantum(void) {
+ matrix_init_kb();
+}
+
+__attribute__ ((weak))
+void matrix_scan_quantum(void) {
+ matrix_scan_kb();
+}
+
+__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();
+
+// TX_RX_LED_INIT;
+
+ // 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 (DEBOUNCING_DELAY > 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 (DEBOUNCING_DELAY > 0)
+ if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
+ 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();
+// // HACK backlighting
+// for (uint8_t t = 0; t < meira_get_backlight_level(); t++) {
+// for (uint8_t x = 0; x < 13; x++) {
+// for (uint8_t y = 0; y < 4; y++) {
+// uint8_t pin = lcol_pins[y];
+// if ((x >> y) & 1) {
+// _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+// } else {
+// _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LO
+// }
+// }
+// }
+// }
+ return ret;
+}
+
+bool matrix_is_modified(void)
+{
+ if (debouncing) return false;
+ return true;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+uint8_t matrix_key_count(void)
+{
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ count += bitpop16(matrix[i]);
+ }
+ return count;
+}
+
+
+static void init_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
+// // HACK backlighting
+// uint8_t lpin = lrow_pins[x];
+// _SFR_IO8((lpin >> 4) + 1) |= _BV(lpin & 0xF); // OUT
+// _SFR_IO8((lpin >> 4) + 2) |= _BV(lpin & 0xF); // HI
+ }
+}
+
+//static void init_lcols(void)
+//{
+// for (uint8_t x = 0; x < 4; x++) {
+// uint8_t pin = lcol_pins[x];
+// _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
+// _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HIGH
+// }
+//}
+
+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/meira/meira.c b/keyboards/meira/meira.c
new file mode 100644
index 000000000..823415920
--- /dev/null
+++ b/keyboards/meira/meira.c
@@ -0,0 +1,145 @@
+/* Copyright 2017 REPLACE_WITH_YOUR_NAME
+ *
+ * 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
+
+#ifdef AUDIO_ENABLE
+ float tone_startup[][2] = SONG(STARTUP_SOUND);
+ float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
+#endif
+
+
+void shutdown_user(void) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_goodbye, false, 0);
+ _delay_ms(150);
+ stop_all_notes();
+ #endif
+}
+
+
+void matrix_init_kb(void)
+{
+ debug_enable=true;
+ print("meira matrix_init_kb\n");
+#ifdef AUDIO_ENABLE
+ _delay_ms(20); // gets rid of tick
+ PLAY_NOTE_ARRAY(tone_startup, false, 0);
+#endif
+
+
+#ifdef ISSI_ENABLE
+ issi_init();
+#endif
+ backlight_set(5);
+#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 led_set_kb(uint8_t usb_led) {
+ // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
+ led_set_user(usb_led);
+}
+
+//void action_function(keyrecord_t *event, uint8_t id, uint8_t opt)
+//{
+//#ifdef AUDIO_ENABLE
+// int8_t sign = 1;
+//#endif
+// if(id == LFK_ESC_TILDE){
+// // Send ~ on shift-esc
+// void (*method)(uint8_t) = (event->event.pressed) ? &add_key : &del_key;
+// uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT));
+// method(shifted ? KC_GRAVE : KC_ESCAPE);
+// send_keyboard_report();
+// }else if(event->event.pressed){
+// switch(id){
+// case LFK_CLEAR:
+// // Go back to default layer
+// layer_clear();
+// break;
+//#ifdef ISSI_ENABLE
+// case LFK_LED_TEST:
+// led_test();
+// break;
+//#endif
+// }
+// }
+//}
+
+void reset_keyboard_kb(){
+#ifdef WATCHDOG_ENABLE
+ MCUSR = 0;
+ wdt_disable();
+ wdt_reset();
+#endif
+ xprintf("programming!\n");
+ reset_keyboard();
+}
diff --git a/keyboards/meira/meira.h b/keyboards/meira/meira.h
new file mode 100644
index 000000000..db84f7221
--- /dev/null
+++ b/keyboards/meira/meira.h
@@ -0,0 +1,48 @@
+/* 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/>.
+ */
+#ifndef MEIRA_H
+#define MEIRA_H
+
+
+#ifdef SUBPROJECT_featherble
+ #include "featherble.h"
+#endif
+#ifdef SUBPROJECT_promicro
+ #include "promicro.h"
+#endif
+
+#include "quantum.h"
+
+void reset_keyboard_kb(void);
+
+// This a shortcut to help you visually see your layout.
+// The following is an example using the Planck MIT layout
+// The first section contains all of the arguments
+// The second converts the arguments into a two-dimensional array
+#define KEYMAP( \
+ 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 } \
+}
+
+#endif
diff --git a/keyboards/meira/promicro/config.h b/keyboards/meira/promicro/config.h
new file mode 100644
index 000000000..403a4e047
--- /dev/null
+++ b/keyboards/meira/promicro/config.h
@@ -0,0 +1,168 @@
+/*
+Copyright 2017 REPLACE_WITH_YOUR_NAME
+
+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 PROMICROCONFIG_H
+#define PROMICROCONFIG_H
+
+#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 }
+#define LED_EN_PIN D2
+#define UNUSED_PINS
+
+#define CATERINA_BOOTLOADER
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 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
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * 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
+
+/*
+ * MIDI options
+ */
+
+/* Prevent use of disabled MIDI features in the keymap */
+//#define MIDI_ENABLE_STRICT 1
+
+/* enable basic MIDI features:
+ - MIDI notes can be sent when in Music mode is on
+*/
+//#define MIDI_BASIC
+
+/* enable advanced MIDI features:
+ - MIDI notes can be added to the keymap
+ - Octave shift and transpose
+ - Virtual sustain, portamento, and modulation wheel
+ - etc.
+*/
+//#define MIDI_ADVANCED
+
+/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
+//#define MIDI_TONE_KEYCODE_OCTAVES 1
+
+#endif
diff --git a/keyboards/meira/promicro/promicro.c b/keyboards/meira/promicro/promicro.c
new file mode 100644
index 000000000..cf579c89b
--- /dev/null
+++ b/keyboards/meira/promicro/promicro.c
@@ -0,0 +1,2 @@
+#include "meira.h"
+
diff --git a/keyboards/meira/promicro/promicro.h b/keyboards/meira/promicro/promicro.h
new file mode 100644
index 000000000..8e7525eab
--- /dev/null
+++ b/keyboards/meira/promicro/promicro.h
@@ -0,0 +1,10 @@
+#ifndef FEATHERBLE_H
+#define FEATHERBLE_H
+
+#include "../meira.h"
+
+#include "quantum.h"
+
+#include "pro_micro.h"
+
+#endif
diff --git a/keyboards/meira/promicro/rules.mk b/keyboards/meira/promicro/rules.mk
new file mode 100644
index 000000000..8d6c4e168
--- /dev/null
+++ b/keyboards/meira/promicro/rules.mk
@@ -0,0 +1,2 @@
+BLUETOOTH_ENABLE = no
+BACKLIGHT_ENABLE = yes
diff --git a/keyboards/meira/readme.md b/keyboards/meira/readme.md
new file mode 100644
index 000000000..ef69b1a80
--- /dev/null
+++ b/keyboards/meira/readme.md
@@ -0,0 +1,28 @@
+meira keyboard firmware
+======================
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme](/).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/meira folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use the Teensy Loader to program your .hex file.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+
+To build with the default keymap, simply run `make default`.
+
+### Other Keymaps
+
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create a folder with the name of your keymap in the keymaps folder, and see keymap documentation (you can find in top readme.md) and existant keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with a keymap like this:
+
+```
+$ make [default|jack|<name>]
+```
+
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
diff --git a/keyboards/meira/rules.mk b/keyboards/meira/rules.mk
new file mode 100644
index 000000000..fa80ca9d4
--- /dev/null
+++ b/keyboards/meira/rules.mk
@@ -0,0 +1,84 @@
+SRC += matrix.c TWIlib.c issi.c lighting.c
+
+# MCU name
+#MCU = at90usb1286
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+NKRO_ENABLE ?= no # USB Nkey Rollover
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality on B7 by default
+MIDI_ENABLE ?= no # MIDI support (+2400 to 4200, depending on config)
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+AUDIO_ENABLE ?= no # Audio output on port C6
+RGBLIGHT_ENABLE ?= no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+FAUXCLICKY_ENABLE ?= no # Use buzzer to emulate clicky switches
+
+ISSI_ENABLE = yes # If the I2C pullup resistors aren't install this must be disabled
+#WATCHDOG_ENABLE = yes # Resets keyboard if matrix_scan isn't run every 250ms
+
+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