From 6e27f6fbde47804035d508eb84690ed7ee9acee7 Mon Sep 17 00:00:00 2001 From: climbalima Date: Thu, 10 Nov 2016 18:19:13 -0500 Subject: [PATCH 1/5] Changes to be committed: new file: keyboards/lets_splitv2/Makefile new file: keyboards/lets_splitv2/config.h new file: keyboards/lets_splitv2/i2c.c new file: keyboards/lets_splitv2/i2c.h new file: keyboards/lets_splitv2/imgs/split-keyboard-i2c-schematic.png new file: keyboards/lets_splitv2/imgs/split-keyboard-serial-schematic.png new file: keyboards/lets_splitv2/keymaps/default/keymap.c new file: keyboards/lets_splitv2/lets_split.c new file: keyboards/lets_splitv2/lets_split.h new file: keyboards/lets_splitv2/matrix.c new file: keyboards/lets_splitv2/pro_micro.h new file: keyboards/lets_splitv2/readme.md new file: keyboards/lets_splitv2/serial.c new file: keyboards/lets_splitv2/serial.h new file: keyboards/lets_splitv2/split_util.c new file: keyboards/lets_splitv2/split_util.h new file: keyboards/maxipad/Makefile new file: keyboards/maxipad/config.h new file: keyboards/maxipad/keymaps/default/Makefile new file: keyboards/maxipad/keymaps/default/config.h new file: keyboards/maxipad/keymaps/default/keymap.c new file: keyboards/maxipad/keymaps/default/readme.md new file: keyboards/maxipad/maxipad.c new file: keyboards/maxipad/maxipad.h new file: keyboards/maxipad/readme.md --- keyboards/lets_split/Makefile | 2 +- keyboards/lets_split/config.h | 6 +- keyboards/lets_split/keymaps/default/keymap.c | 65 +--- keyboards/lets_split/lets_split.h | 8 +- keyboards/lets_splitv2/Makefile | 78 ++++ keyboards/lets_splitv2/config.h | 98 +++++ keyboards/lets_splitv2/i2c.c | 159 ++++++++ keyboards/lets_splitv2/i2c.h | 31 ++ .../imgs/split-keyboard-i2c-schematic.png | Bin 0 -> 26565 bytes .../imgs/split-keyboard-serial-schematic.png | Bin 0 -> 19487 bytes .../lets_splitv2/keymaps/default/keymap.c | 159 ++++++++ keyboards/lets_splitv2/lets_split.c | 30 ++ keyboards/lets_splitv2/lets_split.h | 25 ++ keyboards/lets_splitv2/matrix.c | 311 +++++++++++++++ keyboards/lets_splitv2/pro_micro.h | 362 ++++++++++++++++++ keyboards/lets_splitv2/readme.md | 102 +++++ keyboards/lets_splitv2/serial.c | 225 +++++++++++ keyboards/lets_splitv2/serial.h | 26 ++ keyboards/lets_splitv2/split_util.c | 76 ++++ keyboards/lets_splitv2/split_util.h | 22 ++ keyboards/maxipad/Makefile | 75 ++++ keyboards/maxipad/config.h | 162 ++++++++ keyboards/maxipad/keymaps/default/Makefile | 21 + keyboards/maxipad/keymaps/default/config.h | 8 + keyboards/maxipad/keymaps/default/keymap.c | 54 +++ keyboards/maxipad/keymaps/default/readme.md | 1 + keyboards/maxipad/maxipad.c | 28 ++ keyboards/maxipad/maxipad.h | 25 ++ keyboards/maxipad/readme.md | 28 ++ 29 files changed, 2119 insertions(+), 68 deletions(-) create mode 100644 keyboards/lets_splitv2/Makefile create mode 100644 keyboards/lets_splitv2/config.h create mode 100644 keyboards/lets_splitv2/i2c.c create mode 100644 keyboards/lets_splitv2/i2c.h create mode 100644 keyboards/lets_splitv2/imgs/split-keyboard-i2c-schematic.png create mode 100644 keyboards/lets_splitv2/imgs/split-keyboard-serial-schematic.png create mode 100644 keyboards/lets_splitv2/keymaps/default/keymap.c create mode 100644 keyboards/lets_splitv2/lets_split.c create mode 100644 keyboards/lets_splitv2/lets_split.h create mode 100644 keyboards/lets_splitv2/matrix.c create mode 100644 keyboards/lets_splitv2/pro_micro.h create mode 100644 keyboards/lets_splitv2/readme.md create mode 100644 keyboards/lets_splitv2/serial.c create mode 100644 keyboards/lets_splitv2/serial.h create mode 100644 keyboards/lets_splitv2/split_util.c create mode 100644 keyboards/lets_splitv2/split_util.h create mode 100644 keyboards/maxipad/Makefile create mode 100644 keyboards/maxipad/config.h create mode 100644 keyboards/maxipad/keymaps/default/Makefile create mode 100644 keyboards/maxipad/keymaps/default/config.h create mode 100644 keyboards/maxipad/keymaps/default/keymap.c create mode 100644 keyboards/maxipad/keymaps/default/readme.md create mode 100644 keyboards/maxipad/maxipad.c create mode 100644 keyboards/maxipad/maxipad.h create mode 100644 keyboards/maxipad/readme.md diff --git a/keyboards/lets_split/Makefile b/keyboards/lets_split/Makefile index b9f07636be..982cfc591b 100644 --- a/keyboards/lets_split/Makefile +++ b/keyboards/lets_split/Makefile @@ -67,7 +67,7 @@ AUDIO_ENABLE ?= yes # Audio output on port C6 UNICODE_ENABLE ?= no # Unicode BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID RGBLIGHT_ENABLE ?= no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time. - +USE_I2C ?= yes # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend diff --git a/keyboards/lets_split/config.h b/keyboards/lets_split/config.h index 6f90997ab4..bf618704cd 100644 --- a/keyboards/lets_split/config.h +++ b/keyboards/lets_split/config.h @@ -25,7 +25,7 @@ along with this program. If not, see . #define PRODUCT_ID 0x3060 #define DEVICE_VER 0x0001 #define MANUFACTURER Wootpatoot -#define PRODUCT Lets Split +#define PRODUCT Lets Split v2 #define DESCRIPTION A split keyboard for the cheap makers /* key matrix size */ @@ -34,8 +34,8 @@ along with this program. If not, see . #define MATRIX_COLS 6 // wiring of each half -#define MATRIX_ROW_PINS { B5, B4, E6, D7 } -#define MATRIX_COL_PINS { F4, F5, F6, F7, B1, B3 } +#define MATRIX_ROW_PINS { D7, E6, B4, B5 } +#define MATRIX_COL_PINS { F6, F7, B1, B3, B2, B6 } #define CATERINA_BOOTLOADER diff --git a/keyboards/lets_split/keymaps/default/keymap.c b/keyboards/lets_split/keymaps/default/keymap.c index 0d2d94b672..8c8466ebd5 100644 --- a/keyboards/lets_split/keymaps/default/keymap.c +++ b/keyboards/lets_split/keymaps/default/keymap.c @@ -42,64 +42,17 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * `-----------------------------------------------------------------------------------' */ [_QWERTY] = KEYMAP( \ - 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_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_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \ + KC_LCTL, _LOWER, KC_LGUI, KC_LALT, MO(_LOWER), KC_SPC, KC_LSFT, MO(_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 | - * |------+------+------+------+------+-------------+------+------+------+------+------| - * | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | | \ | | | - * |------+------+------+------+------+------|------+------+------+------+------+------| - * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter | - * |------+------+------+------+------+------+------+------+------+------+------+------| - * | | | | | | | | Next | Vol- | Vol+ | Play | - * `-----------------------------------------------------------------------------------' - */ [_LOWER] = KEYMAP( \ 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_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______, \ - _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \ + _______, _______, _______, _______, _______, KC_BSPC, KC_BSPC, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \ ), /* Raise @@ -117,7 +70,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 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_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______, \ - _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \ + _______, _______, _______, _______, _______, KC_ENT, KC_ENT, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \ ), /* Adjust (Lower + Raise) @@ -131,14 +84,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | | | | | | | | | | | | * `-----------------------------------------------------------------------------------' */ -[_ADJUST] = KEYMAP( \ - _______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL, \ - _______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______, \ - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ -) - - }; #ifdef AUDIO_ENABLE diff --git a/keyboards/lets_split/lets_split.h b/keyboards/lets_split/lets_split.h index fe7ae07679..04844ed639 100644 --- a/keyboards/lets_split/lets_split.h +++ b/keyboards/lets_split/lets_split.h @@ -6,10 +6,10 @@ void promicro_bootloader_jmp(bool program); #define KEYMAP( \ - k00, k01, k02, k03, k04, k05, k40, k41, k42, k43, k44, k45, \ - k10, k11, k12, k13, k14, k15, k50, k51, k52, k53, k54, k55, \ - k20, k21, k22, k23, k24, k25, k60, k61, k62, k63, k64, k65, \ - k30, k31, k32, k33, k34, k35, k70, k71, k72, k73, k74, k75 \ + k00, k01, k02, k03, k04, k05, k45, k44, k43, k42, k41, k40, \ + k10, k11, k12, k13, k14, k15, k55, k54, k53, k52, k51, k50, \ + k20, k21, k22, k23, k24, k25, k65, k64, k63, k62, k61, k60, \ + k30, k31, k32, k33, k34, k35, k75, k74, k73, k72, k71, k70 \ ) \ { \ { k00, k01, k02, k03, k04, k05 }, \ diff --git a/keyboards/lets_splitv2/Makefile b/keyboards/lets_splitv2/Makefile new file mode 100644 index 0000000000..982cfc591b --- /dev/null +++ b/keyboards/lets_splitv2/Makefile @@ -0,0 +1,78 @@ +SRC += matrix.c \ + i2c.c \ + split_util.c \ + serial.c + +# MCU name +#MCU = at90usb1287 +MCU = atmega32u4 + +# Processor frequency. +# This will define a symbol, F_CPU, in all source code files equal to the +# processor frequency in Hz. You can then use this symbol in your source code to +# calculate timings. Do NOT tack on a 'UL' at the end, this will be done +# automatically to create a 32-bit value in your source code. +# +# This will be an integer division of F_USB below, as it is sourced by +# F_USB after it has run through any CPU prescalers. Note that this value +# does not *change* the processor frequency - it should merely be updated to +# reflect the processor speed set externally so that the code can use accurate +# software delays. +F_CPU = 16000000 + +# +# LUFA specific +# +# Target architecture (see library "Board Types" documentation). +ARCH = AVR8 + +# Input clock frequency. +# This will define a symbol, F_USB, in all source code files equal to the +# input clock frequency (before any prescaling is performed) in Hz. This value may +# differ from F_CPU if prescaling is used on the latter, and is required as the +# raw input clock is fed directly to the PLL sections of the AVR for high speed +# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' +# at the end, this will be done automatically to create a 32-bit value in your +# source code. +# +# If no clock division is performed on the input clock inside the AVR (via the +# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. +F_USB = $(F_CPU) + +# Interrupt driven control endpoint task(+60) +OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT + + +# Boot Section Size in *bytes* +# Teensy halfKay 512 +# Teensy++ halfKay 1024 +# Atmel DFU loader 4096 +# LUFA bootloader 4096 +# USBaspLoader 2048 +OPT_DEFS += -DBOOTLOADER_SIZE=4096 + +# Build Options +# change to "no" to disable the options, or define them in the Makefile in +# the appropriate keymap folder that will get included automatically +# +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 ?= no # Console for debug(+400) +COMMAND_ENABLE ?= yes # Commands for debug and configuration +NKRO_ENABLE ?= no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work +BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality +MIDI_ENABLE ?= no # MIDI controls +AUDIO_ENABLE ?= yes # Audio output on port C6 +UNICODE_ENABLE ?= no # Unicode +BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID +RGBLIGHT_ENABLE ?= no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time. +USE_I2C ?= yes +# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE +SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend + +CUSTOM_MATRIX = yes + +ifndef QUANTUM_DIR + include ../../Makefile +endif \ No newline at end of file diff --git a/keyboards/lets_splitv2/config.h b/keyboards/lets_splitv2/config.h new file mode 100644 index 0000000000..bf618704cd --- /dev/null +++ b/keyboards/lets_splitv2/config.h @@ -0,0 +1,98 @@ +/* +Copyright 2012 Jun Wako + +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 . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x3060 +#define DEVICE_VER 0x0001 +#define MANUFACTURER Wootpatoot +#define PRODUCT Lets Split v2 +#define DESCRIPTION A split keyboard for the cheap makers + +/* key matrix size */ +// Rows are doubled-up +#define MATRIX_ROWS 8 +#define MATRIX_COLS 6 + +// wiring of each half +#define MATRIX_ROW_PINS { D7, E6, B4, B5 } +#define MATRIX_COL_PINS { F6, F7, B1, B3, B2, B6 } + +#define CATERINA_BOOTLOADER + +// #define USE_I2C + +// #define EE_HANDS + +#define I2C_MASTER_LEFT +// #define I2C_MASTER_RIGHT + +/* COL2ROW or ROW2COL */ +#define DIODE_DIRECTION COL2ROW + +/* define if matrix has ghost */ +//#define MATRIX_HAS_GHOST + +/* number of backlight levels */ +// #define BACKLIGHT_LEVELS 3 + +/* Set 0 if debouncing isn't needed */ +#define DEBOUNCING_DELAY 5 + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +#define LOCKING_RESYNC_ENABLE + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* ws2812 RGB LED */ +#define ws2812_PORTREG PORTD +#define ws2812_DDRREG DDRD +#define ws2812_pin PD1 +#define RGBLED_NUM 28 // Number of LEDs +#define RGBLIGHT_HUE_STEP 10 +#define RGBLIGHT_SAT_STEP 17 +#define RGBLIGHT_VAL_STEP 17 + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +// #define NO_DEBUG + +/* disable print */ +// #define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION + +#endif \ No newline at end of file diff --git a/keyboards/lets_splitv2/i2c.c b/keyboards/lets_splitv2/i2c.c new file mode 100644 index 0000000000..c72789403e --- /dev/null +++ b/keyboards/lets_splitv2/i2c.c @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include +#include "i2c.h" + +// Limits the amount of we wait for any one i2c transaction. +// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is +// 9 bits, a single transaction will take around 90μs to complete. +// +// (F_CPU/SCL_CLOCK) => # of μC cycles to transfer a bit +// poll loop takes at least 8 clock cycles to execute +#define I2C_LOOP_TIMEOUT (9+1)*(F_CPU/SCL_CLOCK)/8 + +#define BUFFER_POS_INC() (slave_buffer_pos = (slave_buffer_pos+1)%SLAVE_BUFFER_SIZE) + +volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE]; + +static volatile uint8_t slave_buffer_pos; +static volatile bool slave_has_register_set = false; + +// Wait for an i2c operation to finish +inline static +void i2c_delay(void) { + uint16_t lim = 0; + while(!(TWCR & (1<10. + // Check datasheets for more info. + TWBR = ((F_CPU/SCL_CLOCK)-16)/2; +} + +// Start a transaction with the given i2c slave address. The direction of the +// transfer is set with I2C_READ and I2C_WRITE. +// returns: 0 => success +// 1 => error +uint8_t i2c_master_start(uint8_t address) { + TWCR = (1< slave ACK +// 1 => slave NACK +uint8_t i2c_master_write(uint8_t data) { + TWDR = data; + TWCR = (1<= SLAVE_BUFFER_SIZE ) { + ack = 0; + slave_buffer_pos = 0; + } + slave_has_register_set = true; + } else { + i2c_slave_buffer[slave_buffer_pos] = TWDR; + BUFFER_POS_INC(); + } + break; + + case TW_ST_SLA_ACK: + case TW_ST_DATA_ACK: + // master has addressed this device as a slave transmitter and is + // requesting data. + TWDR = i2c_slave_buffer[slave_buffer_pos]; + BUFFER_POS_INC(); + break; + + case TW_BUS_ERROR: // something went wrong, reset twi state + TWCR = 0; + default: + break; + } + // Reset everything, so we are ready for the next TWI interrupt + TWCR |= (1< + +#ifndef F_CPU +#define F_CPU 16000000UL +#endif + +#define I2C_READ 1 +#define I2C_WRITE 0 + +#define I2C_ACK 1 +#define I2C_NACK 0 + +#define SLAVE_BUFFER_SIZE 0x10 + +// i2c SCL clock frequency +#define SCL_CLOCK 100000L + +extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE]; + +void i2c_master_init(void); +uint8_t i2c_master_start(uint8_t address); +void i2c_master_stop(void); +uint8_t i2c_master_write(uint8_t data); +uint8_t i2c_master_read(int); +void i2c_reset_state(void); +void i2c_slave_init(uint8_t address); + +#endif diff --git a/keyboards/lets_splitv2/imgs/split-keyboard-i2c-schematic.png b/keyboards/lets_splitv2/imgs/split-keyboard-i2c-schematic.png new file mode 100644 index 0000000000000000000000000000000000000000..8882947187b15ae4c0cf70c90725d67fb2386d87 GIT binary patch literal 26565 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.pressed) { + #ifdef AUDIO_ENABLE + PLAY_NOTE_ARRAY(tone_qwerty, false, 0); + #endif + persistant_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 + persistant_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 + persistant_default_layer_set(1UL<<_DVORAK); + } + 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: + if (record->event.pressed) { + layer_on(_ADJUST); + } else { + layer_off(_ADJUST); + } + return false; + break; + } + return true; +} \ No newline at end of file diff --git a/keyboards/lets_splitv2/lets_split.c b/keyboards/lets_splitv2/lets_split.c new file mode 100644 index 0000000000..574c116a75 --- /dev/null +++ b/keyboards/lets_splitv2/lets_split.c @@ -0,0 +1,30 @@ +#include "lets_split.h" + +#ifdef AUDIO_ENABLE + float tone_startup[][2] = SONG(STARTUP_SOUND); + float tone_goodbye[][2] = SONG(GOODBYE_SOUND); +#endif + +void matrix_init_kb(void) { + + #ifdef AUDIO_ENABLE + _delay_ms(20); // gets rid of tick + PLAY_NOTE_ARRAY(tone_startup, false, 0); + #endif + + // // green led on + // DDRD |= (1<<5); + // PORTD &= ~(1<<5); + + // // orange led on + // DDRB |= (1<<0); + // PORTB &= ~(1<<0); + + matrix_init_user(); +}; + +void shutdown_user(void) { + PLAY_NOTE_ARRAY(tone_goodbye, false, 0); + _delay_ms(150); + stop_all_notes(); +} diff --git a/keyboards/lets_splitv2/lets_split.h b/keyboards/lets_splitv2/lets_split.h new file mode 100644 index 0000000000..04844ed639 --- /dev/null +++ b/keyboards/lets_splitv2/lets_split.h @@ -0,0 +1,25 @@ +#ifndef LETS_SPLIT_H +#define LETS_SPLIT_H + +#include "quantum.h" + +void promicro_bootloader_jmp(bool program); + +#define KEYMAP( \ + k00, k01, k02, k03, k04, k05, k45, k44, k43, k42, k41, k40, \ + k10, k11, k12, k13, k14, k15, k55, k54, k53, k52, k51, k50, \ + k20, k21, k22, k23, k24, k25, k65, k64, k63, k62, k61, k60, \ + k30, k31, k32, k33, k34, k35, k75, k74, k73, k72, k71, k70 \ + ) \ + { \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k40, k41, k42, k43, k44, k45 }, \ + { k50, k51, k52, k53, k54, k55 }, \ + { k60, k61, k62, k63, k64, k65 }, \ + { k70, k71, k72, k73, k74, k75 } \ + } + +#endif \ No newline at end of file diff --git a/keyboards/lets_splitv2/matrix.c b/keyboards/lets_splitv2/matrix.c new file mode 100644 index 0000000000..1d768c59b3 --- /dev/null +++ b/keyboards/lets_splitv2/matrix.c @@ -0,0 +1,311 @@ +/* +Copyright 2012 Jun Wako + +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 . +*/ + +/* + * scan matrix + */ +#include +#include +#include +#include +#include +#include +#include "print.h" +#include "debug.h" +#include "util.h" +#include "matrix.h" +#include "i2c.h" +#include "serial.h" +#include "split_util.h" +#include "pro_micro.h" +#include "config.h" + +#ifndef DEBOUNCE +# define DEBOUNCE 5 +#endif + +#define ERROR_DISCONNECT_COUNT 5 + +static uint8_t debouncing = DEBOUNCE; +static const int ROWS_PER_HAND = MATRIX_ROWS/2; +static uint8_t error_count = 0; + +static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; +static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; + +/* matrix state(1:on, 0:off) */ +static matrix_row_t matrix[MATRIX_ROWS]; +static matrix_row_t matrix_debouncing[MATRIX_ROWS]; + +static matrix_row_t read_cols(void); +static void init_cols(void); +static void unselect_rows(void); +static void select_row(uint8_t row); + +__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_rows(); + init_cols(); + + 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) +{ + // Right hand is stored after the left in the matirx so, we need to offset it + int offset = isLeftHand ? 0 : (ROWS_PER_HAND); + + for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { + select_row(i); + _delay_us(30); // without this wait read unstable value. + matrix_row_t cols = read_cols(); + if (matrix_debouncing[i+offset] != cols) { + matrix_debouncing[i+offset] = cols; + debouncing = DEBOUNCE; + } + unselect_rows(); + } + + if (debouncing) { + if (--debouncing) { + _delay_ms(1); + } else { + for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { + matrix[i+offset] = matrix_debouncing[i+offset]; + } + } + } + + return 1; +} + +// Get rows from other half over i2c +int i2c_transaction(void) { + int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; + + int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE); + if (err) goto i2c_error; + + // start of matrix stored at 0x00 + err = i2c_master_write(0x00); + if (err) goto i2c_error; + + // Start read + err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ); + if (err) goto i2c_error; + + if (!err) { + int i; + for (i = 0; i < ROWS_PER_HAND-1; ++i) { + matrix[slaveOffset+i] = i2c_master_read(I2C_ACK); + } + matrix[slaveOffset+i] = i2c_master_read(I2C_NACK); + i2c_master_stop(); + } else { +i2c_error: // the cable is disconnceted, or something else went wrong + i2c_reset_state(); + return err; + } + + return 0; +} + +#ifndef USE_I2C +int serial_transaction(void) { + int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; + + if (serial_update_buffers()) { + return 1; + } + + for (int i = 0; i < ROWS_PER_HAND; ++i) { + matrix[slaveOffset+i] = serial_slave_buffer[i]; + } + return 0; +} +#endif + +uint8_t matrix_scan(void) +{ + int ret = _matrix_scan(); + + + +#ifdef USE_I2C + if( i2c_transaction() ) { +#else + if( serial_transaction() ) { +#endif + // turn on the indicator led when halves are disconnected + TXLED1; + + error_count++; + + if (error_count > ERROR_DISCONNECT_COUNT) { + // reset other half if disconnected + int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; + for (int i = 0; i < ROWS_PER_HAND; ++i) { + matrix[slaveOffset+i] = 0; + } + } + } else { + // turn off the indicator led on no error + TXLED0; + error_count = 0; + } + + matrix_scan_quantum(); + + return ret; +} + +void matrix_slave_scan(void) { + _matrix_scan(); + + int offset = (isLeftHand) ? 0 : (MATRIX_ROWS / 2); + +#ifdef USE_I2C + for (int i = 0; i < ROWS_PER_HAND; ++i) { + /* i2c_slave_buffer[i] = matrix[offset+i]; */ + i2c_slave_buffer[i] = matrix[offset+i]; + } +#else + for (int i = 0; i < ROWS_PER_HAND; ++i) { + serial_slave_buffer[i] = matrix[offset+i]; + } +#endif +} + +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<> 4) + 1) &= ~_BV(col_pins[x] & 0xF); + _SFR_IO8((col_pins[x] >> 4) + 2) |= _BV(col_pins[x] & 0xF); + } +} + +static matrix_row_t read_cols(void) +{ + matrix_row_t result = 0; + for(int x = 0; x < MATRIX_COLS; x++) { + result |= (_SFR_IO8(col_pins[x] >> 4) & _BV(col_pins[x] & 0xF)) ? 0 : (1 << x); + } + return result; +} + +static void unselect_rows(void) +{ + for(int x = 0; x < ROWS_PER_HAND; x++) { + _SFR_IO8((row_pins[x] >> 4) + 1) &= ~_BV(row_pins[x] & 0xF); + _SFR_IO8((row_pins[x] >> 4) + 2) |= _BV(row_pins[x] & 0xF); + } +} + +static void select_row(uint8_t row) +{ + _SFR_IO8((row_pins[row] >> 4) + 1) |= _BV(row_pins[row] & 0xF); + _SFR_IO8((row_pins[row] >> 4) + 2) &= ~_BV(row_pins[row] & 0xF); +} diff --git a/keyboards/lets_splitv2/pro_micro.h b/keyboards/lets_splitv2/pro_micro.h new file mode 100644 index 0000000000..09e219b7b1 --- /dev/null +++ b/keyboards/lets_splitv2/pro_micro.h @@ -0,0 +1,362 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// Workaround for wrong definitions in "iom32u4.h". +// This should be fixed in the AVR toolchain. +#undef UHCON +#undef UHINT +#undef UHIEN +#undef UHADDR +#undef UHFNUM +#undef UHFNUML +#undef UHFNUMH +#undef UHFLEN +#undef UPINRQX +#undef UPINTX +#undef UPNUM +#undef UPRST +#undef UPCONX +#undef UPCFG0X +#undef UPCFG1X +#undef UPSTAX +#undef UPCFG2X +#undef UPIENX +#undef UPDATX +#undef TCCR2A +#undef WGM20 +#undef WGM21 +#undef COM2B0 +#undef COM2B1 +#undef COM2A0 +#undef COM2A1 +#undef TCCR2B +#undef CS20 +#undef CS21 +#undef CS22 +#undef WGM22 +#undef FOC2B +#undef FOC2A +#undef TCNT2 +#undef TCNT2_0 +#undef TCNT2_1 +#undef TCNT2_2 +#undef TCNT2_3 +#undef TCNT2_4 +#undef TCNT2_5 +#undef TCNT2_6 +#undef TCNT2_7 +#undef OCR2A +#undef OCR2_0 +#undef OCR2_1 +#undef OCR2_2 +#undef OCR2_3 +#undef OCR2_4 +#undef OCR2_5 +#undef OCR2_6 +#undef OCR2_7 +#undef OCR2B +#undef OCR2_0 +#undef OCR2_1 +#undef OCR2_2 +#undef OCR2_3 +#undef OCR2_4 +#undef OCR2_5 +#undef OCR2_6 +#undef OCR2_7 + +#define NUM_DIGITAL_PINS 30 +#define NUM_ANALOG_INPUTS 12 + +#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0) +#define TXLED0 PORTD |= (1<<5) +#define TXLED1 PORTD &= ~(1<<5) +#define RXLED0 PORTB |= (1<<0) +#define RXLED1 PORTB &= ~(1<<0) + +static const uint8_t SDA = 2; +static const uint8_t SCL = 3; +#define LED_BUILTIN 13 + +// Map SPI port to 'new' pins D14..D17 +static const uint8_t SS = 17; +static const uint8_t MOSI = 16; +static const uint8_t MISO = 14; +static const uint8_t SCK = 15; + +// Mapping of analog pins as digital I/O +// A6-A11 share with digital pins +static const uint8_t A0 = 18; +static const uint8_t A1 = 19; +static const uint8_t A2 = 20; +static const uint8_t A3 = 21; +static const uint8_t A4 = 22; +static const uint8_t A5 = 23; +static const uint8_t A6 = 24; // D4 +static const uint8_t A7 = 25; // D6 +static const uint8_t A8 = 26; // D8 +static const uint8_t A9 = 27; // D9 +static const uint8_t A10 = 28; // D10 +static const uint8_t A11 = 29; // D12 + +#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) +#define digitalPinToPCICRbit(p) 0 +#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) +#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) + +// __AVR_ATmega32U4__ has an unusual mapping of pins to channels +extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; +#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) ) + +#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) + +#ifdef ARDUINO_MAIN + +// On the Arduino board, digital pins are also used +// for the analog output (software PWM). Analog input +// pins are a separate set. + +// ATMEL ATMEGA32U4 / ARDUINO LEONARDO +// +// D0 PD2 RXD1/INT2 +// D1 PD3 TXD1/INT3 +// D2 PD1 SDA SDA/INT1 +// D3# PD0 PWM8/SCL OC0B/SCL/INT0 +// D4 A6 PD4 ADC8 +// D5# PC6 ??? OC3A/#OC4A +// D6# A7 PD7 FastPWM #OC4D/ADC10 +// D7 PE6 INT6/AIN0 +// +// D8 A8 PB4 ADC11/PCINT4 +// D9# A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5 +// D10# A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6 +// D11# PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7 +// D12 A11 PD6 T1/#OC4D/ADC9 +// D13# PC7 PWM10 CLK0/OC4A +// +// A0 D18 PF7 ADC7 +// A1 D19 PF6 ADC6 +// A2 D20 PF5 ADC5 +// A3 D21 PF4 ADC4 +// A4 D22 PF1 ADC1 +// A5 D23 PF0 ADC0 +// +// New pins D14..D17 to map SPI port to digital pins +// +// MISO D14 PB3 MISO,PCINT3 +// SCK D15 PB1 SCK,PCINT1 +// MOSI D16 PB2 MOSI,PCINT2 +// SS D17 PB0 RXLED,SS/PCINT0 +// +// Connected LEDs on board for TX and RX +// TXLED D24 PD5 XCK1 +// RXLED D17 PB0 +// HWB PE2 HWB + +// these arrays map port names (e.g. port B) to the +// appropriate addresses for various functions (e.g. reading +// and writing) +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, + (uint16_t) &DDRE, + (uint16_t) &DDRF, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, + (uint16_t) &PORTE, + (uint16_t) &PORTF, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, + (uint16_t) &PINE, + (uint16_t) &PINF, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = { + PD, // D0 - PD2 + PD, // D1 - PD3 + PD, // D2 - PD1 + PD, // D3 - PD0 + PD, // D4 - PD4 + PC, // D5 - PC6 + PD, // D6 - PD7 + PE, // D7 - PE6 + + PB, // D8 - PB4 + PB, // D9 - PB5 + PB, // D10 - PB6 + PB, // D11 - PB7 + PD, // D12 - PD6 + PC, // D13 - PC7 + + PB, // D14 - MISO - PB3 + PB, // D15 - SCK - PB1 + PB, // D16 - MOSI - PB2 + PB, // D17 - SS - PB0 + + PF, // D18 - A0 - PF7 + PF, // D19 - A1 - PF6 + PF, // D20 - A2 - PF5 + PF, // D21 - A3 - PF4 + PF, // D22 - A4 - PF1 + PF, // D23 - A5 - PF0 + + PD, // D24 - PD5 + PD, // D25 / D6 - A7 - PD7 + PB, // D26 / D8 - A8 - PB4 + PB, // D27 / D9 - A9 - PB5 + PB, // D28 / D10 - A10 - PB6 + PD, // D29 / D12 - A11 - PD6 +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { + _BV(2), // D0 - PD2 + _BV(3), // D1 - PD3 + _BV(1), // D2 - PD1 + _BV(0), // D3 - PD0 + _BV(4), // D4 - PD4 + _BV(6), // D5 - PC6 + _BV(7), // D6 - PD7 + _BV(6), // D7 - PE6 + + _BV(4), // D8 - PB4 + _BV(5), // D9 - PB5 + _BV(6), // D10 - PB6 + _BV(7), // D11 - PB7 + _BV(6), // D12 - PD6 + _BV(7), // D13 - PC7 + + _BV(3), // D14 - MISO - PB3 + _BV(1), // D15 - SCK - PB1 + _BV(2), // D16 - MOSI - PB2 + _BV(0), // D17 - SS - PB0 + + _BV(7), // D18 - A0 - PF7 + _BV(6), // D19 - A1 - PF6 + _BV(5), // D20 - A2 - PF5 + _BV(4), // D21 - A3 - PF4 + _BV(1), // D22 - A4 - PF1 + _BV(0), // D23 - A5 - PF0 + + _BV(5), // D24 - PD5 + _BV(7), // D25 / D6 - A7 - PD7 + _BV(4), // D26 / D8 - A8 - PB4 + _BV(5), // D27 / D9 - A9 - PB5 + _BV(6), // D28 / D10 - A10 - PB6 + _BV(6), // D29 / D12 - A11 - PD6 +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + TIMER0B, /* 3 */ + NOT_ON_TIMER, + TIMER3A, /* 5 */ + TIMER4D, /* 6 */ + NOT_ON_TIMER, + + NOT_ON_TIMER, + TIMER1A, /* 9 */ + TIMER1B, /* 10 */ + TIMER0A, /* 11 */ + + NOT_ON_TIMER, + TIMER4A, /* 13 */ + + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, +}; + +const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { + 7, // A0 PF7 ADC7 + 6, // A1 PF6 ADC6 + 5, // A2 PF5 ADC5 + 4, // A3 PF4 ADC4 + 1, // A4 PF1 ADC1 + 0, // A5 PF0 ADC0 + 8, // A6 D4 PD4 ADC8 + 10, // A7 D6 PD7 ADC10 + 11, // A8 D8 PB4 ADC11 + 12, // A9 D9 PB5 ADC12 + 13, // A10 D10 PB6 ADC13 + 9 // A11 D12 PD6 ADC9 +}; + +#endif /* ARDUINO_MAIN */ + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_USBVIRTUAL Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_HARDWARE_OPEN Serial1 + +#endif /* Pins_Arduino_h */ diff --git a/keyboards/lets_splitv2/readme.md b/keyboards/lets_splitv2/readme.md new file mode 100644 index 0000000000..73fdb0f789 --- /dev/null +++ b/keyboards/lets_splitv2/readme.md @@ -0,0 +1,102 @@ +Let's Split +====== + +This readme and most of the code are from https://github.com/ahtn/tmk_keyboard/ + +Split keyboard firmware for Arduino Pro Micro or other ATmega32u4 +based boards. + +Features +-------- + +Some features supported by the firmware: + +* Either half can connect to the computer via USB, or both halves can be used + independently. +* You only need 3 wires to connect the two halves. Two for VCC and GND and one + for serial communication. +* Optional support for I2C connection between the two halves if for some + reason you require a faster connection between the two halves. Note this + requires an extra wire between halves and pull-up resistors on the data lines. + +Required Hardware +----------------- + +Apart from diodes and key switches for the keyboard matrix in each half, you +will need: + +* 2 Arduino Pro Micro's. You can find theses on aliexpress for ≈3.50USD each. +* 2 TRS sockets +* 1 TRS cable. + +Alternatively, you can use any sort of cable and socket that has at least 3 +wires. If you want to use I2C to communicate between halves, you will need a +cable with at least 4 wires and 2x 4.7kΩ pull-up resistors + +Optional Hardware +----------------- + +A speaker can be hooked-up to either side to the `5` (`C6`) pin and `GND`, and turned on via `AUDIO_ENABLE`. + +Wiring +------ + +The 3 wires of the TRS cable need to connect GND, VCC, and digital pin 3 (i.e. +PD0 on the ATmega32u4) between the two Pro Micros. + +Then wire your key matrix to any of the remaining 17 IO pins of the pro micro +and modify the `matrix.c` accordingly. + +The wiring for serial: + +![serial wiring](imgs/split-keyboard-serial-schematic.png) + +The wiring for i2c: + +![i2c wiring](imgs/split-keyboard-i2c-schematic.png) + +The pull-up resistors may be placed on either half. It is also possible +to use 4 resistors and have the pull-ups in both halves, but this is +unnecessary in simple use cases. + +Notes on Software Configuration +------------------------------- + +Configuring the firmware is similar to any other TMK project. One thing +to note is that `MATIX_ROWS` in `config.h` is the total number of rows between +the two halves, i.e. if your split keyboard has 4 rows in each half, then +`MATRIX_ROWS=8`. + +Also the current implementation assumes a maximum of 8 columns, but it would +not be very difficult to adapt it to support more if required. + + +Flashing +-------- + +If you define `EE_HANDS` in your `config.h`, you will need to set the +EEPROM for the left and right halves. The EEPROM is used to store whether the +half is left handed or right handed. This makes it so that the same firmware +file will run on both hands instead of having to flash left and right handed +versions of the firmware to each half. To flash the EEPROM file for the left +half run: +``` +make eeprom-left +``` +and similarly for right half +``` +make eeprom-right +``` + +After you have flashed the EEPROM for the first time, you then need to program +the flash memory: +``` +make program +``` +Note that you need to program both halves, but you have the option of using +different keymaps for each half. You could program the left half with a QWERTY +layout and the right half with a Colemak layout. Then if you connect the left +half to a computer by USB the keyboard will use QWERTY and Colemak when the +right half is connected. + + diff --git a/keyboards/lets_splitv2/serial.c b/keyboards/lets_splitv2/serial.c new file mode 100644 index 0000000000..f439c2f20b --- /dev/null +++ b/keyboards/lets_splitv2/serial.c @@ -0,0 +1,225 @@ +/* + * WARNING: be careful changing this code, it is very timing dependent + */ + +#ifndef F_CPU +#define F_CPU 16000000 +#endif + +#include +#include +#include +#include + +#include "serial.h" + +// Serial pulse period in microseconds. Its probably a bad idea to lower this +// value. +#define SERIAL_DELAY 24 + +uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0}; +uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0}; + +#define SLAVE_DATA_CORRUPT (1<<0) +volatile uint8_t status = 0; + +inline static +void serial_delay(void) { + _delay_us(SERIAL_DELAY); +} + +inline static +void serial_output(void) { + SERIAL_PIN_DDR |= SERIAL_PIN_MASK; +} + +// make the serial pin an input with pull-up resistor +inline static +void serial_input(void) { + SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK; + SERIAL_PIN_PORT |= SERIAL_PIN_MASK; +} + +inline static +uint8_t serial_read_pin(void) { + return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK); +} + +inline static +void serial_low(void) { + SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK; +} + +inline static +void serial_high(void) { + SERIAL_PIN_PORT |= SERIAL_PIN_MASK; +} + +void serial_master_init(void) { + serial_output(); + serial_high(); +} + +void serial_slave_init(void) { + serial_input(); + + // Enable INT0 + EIMSK |= _BV(INT0); + // Trigger on falling edge of INT0 + EICRA &= ~(_BV(ISC00) | _BV(ISC01)); +} + +// Used by the master to synchronize timing with the slave. +static +void sync_recv(void) { + serial_input(); + // This shouldn't hang if the slave disconnects because the + // serial line will float to high if the slave does disconnect. + while (!serial_read_pin()); + serial_delay(); +} + +// Used by the slave to send a synchronization signal to the master. +static +void sync_send(void) { + serial_output(); + + serial_low(); + serial_delay(); + + serial_high(); +} + +// Reads a byte from the serial line +static +uint8_t serial_read_byte(void) { + uint8_t byte = 0; + serial_input(); + for ( uint8_t i = 0; i < 8; ++i) { + byte = (byte << 1) | serial_read_pin(); + serial_delay(); + _delay_us(1); + } + + return byte; +} + +// Sends a byte with MSB ordering +static +void serial_write_byte(uint8_t data) { + uint8_t b = 8; + serial_output(); + while( b-- ) { + if(data & (1 << b)) { + serial_high(); + } else { + serial_low(); + } + serial_delay(); + } +} + +// interrupt handle to be used by the slave device +ISR(SERIAL_PIN_INTERRUPT) { + sync_send(); + + uint8_t checksum = 0; + for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) { + serial_write_byte(serial_slave_buffer[i]); + sync_send(); + checksum += serial_slave_buffer[i]; + } + serial_write_byte(checksum); + sync_send(); + + // wait for the sync to finish sending + serial_delay(); + + // read the middle of pulses + _delay_us(SERIAL_DELAY/2); + + uint8_t checksum_computed = 0; + for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) { + serial_master_buffer[i] = serial_read_byte(); + sync_send(); + checksum_computed += serial_master_buffer[i]; + } + uint8_t checksum_received = serial_read_byte(); + sync_send(); + + serial_input(); // end transaction + + if ( checksum_computed != checksum_received ) { + status |= SLAVE_DATA_CORRUPT; + } else { + status &= ~SLAVE_DATA_CORRUPT; + } +} + +inline +bool serial_slave_DATA_CORRUPT(void) { + return status & SLAVE_DATA_CORRUPT; +} + +// Copies the serial_slave_buffer to the master and sends the +// serial_master_buffer to the slave. +// +// Returns: +// 0 => no error +// 1 => slave did not respond +int serial_update_buffers(void) { + // this code is very time dependent, so we need to disable interrupts + cli(); + + // signal to the slave that we want to start a transaction + serial_output(); + serial_low(); + _delay_us(1); + + // wait for the slaves response + serial_input(); + serial_high(); + _delay_us(SERIAL_DELAY); + + // check if the slave is present + if (serial_read_pin()) { + // slave failed to pull the line low, assume not present + sei(); + return 1; + } + + // if the slave is present syncronize with it + sync_recv(); + + uint8_t checksum_computed = 0; + // receive data from the slave + for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) { + serial_slave_buffer[i] = serial_read_byte(); + sync_recv(); + checksum_computed += serial_slave_buffer[i]; + } + uint8_t checksum_received = serial_read_byte(); + sync_recv(); + + if (checksum_computed != checksum_received) { + sei(); + return 1; + } + + uint8_t checksum = 0; + // send data to the slave + for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) { + serial_write_byte(serial_master_buffer[i]); + sync_recv(); + checksum += serial_master_buffer[i]; + } + serial_write_byte(checksum); + sync_recv(); + + // always, release the line when not in use + serial_output(); + serial_high(); + + sei(); + return 0; +} diff --git a/keyboards/lets_splitv2/serial.h b/keyboards/lets_splitv2/serial.h new file mode 100644 index 0000000000..15fe4db7b4 --- /dev/null +++ b/keyboards/lets_splitv2/serial.h @@ -0,0 +1,26 @@ +#ifndef MY_SERIAL_H +#define MY_SERIAL_H + +#include "config.h" +#include + +/* TODO: some defines for interrupt setup */ +#define SERIAL_PIN_DDR DDRD +#define SERIAL_PIN_PORT PORTD +#define SERIAL_PIN_INPUT PIND +#define SERIAL_PIN_MASK _BV(PD0) +#define SERIAL_PIN_INTERRUPT INT0_vect + +#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2 +#define SERIAL_MASTER_BUFFER_LENGTH 1 + +// Buffers for master - slave communication +extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH]; +extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH]; + +void serial_master_init(void); +void serial_slave_init(void); +int serial_update_buffers(void); +bool serial_slave_data_corrupt(void); + +#endif diff --git a/keyboards/lets_splitv2/split_util.c b/keyboards/lets_splitv2/split_util.c new file mode 100644 index 0000000000..65003a71a4 --- /dev/null +++ b/keyboards/lets_splitv2/split_util.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include +#include "split_util.h" +#include "matrix.h" +#include "i2c.h" +#include "serial.h" +#include "keyboard.h" +#include "config.h" + +volatile bool isLeftHand = true; + +static void setup_handedness(void) { + #ifdef EE_HANDS + isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS); + #else + #ifdef I2C_MASTER_RIGHT + isLeftHand = !has_usb(); + #else + isLeftHand = has_usb(); + #endif + #endif +} + +static void keyboard_master_setup(void) { +#ifdef USE_I2C + i2c_master_init(); +#else + serial_master_init(); +#endif +} + +static void keyboard_slave_setup(void) { +#ifdef USE_I2C + i2c_slave_init(SLAVE_I2C_ADDRESS); +#else + serial_slave_init(); +#endif +} + +bool has_usb(void) { + USBCON |= (1 << OTGPADE); //enables VBUS pad + _delay_us(5); + return (USBSTA & (1< + +#ifdef EE_HANDS + #define EECONFIG_BOOTMAGIC_END (uint8_t *)10 + #define EECONFIG_HANDEDNESS EECONFIG_BOOTMAGIC_END +#endif + +#define SLAVE_I2C_ADDRESS 0x32 + +extern volatile bool isLeftHand; + +// slave version of matix scan, defined in matrix.c +void matrix_slave_scan(void); + +void split_keyboard_setup(void); +bool has_usb(void); +void keyboard_slave_loop(void); + +#endif diff --git a/keyboards/maxipad/Makefile b/keyboards/maxipad/Makefile new file mode 100644 index 0000000000..3f6d133c9b --- /dev/null +++ b/keyboards/maxipad/Makefile @@ -0,0 +1,75 @@ + + +# MCU name +#MCU = at90usb1287 +MCU = atmega32u4 + +# Processor frequency. +# This will define a symbol, F_CPU, in all source code files equal to the +# processor frequency in Hz. You can then use this symbol in your source code to +# calculate timings. Do NOT tack on a 'UL' at the end, this will be done +# automatically to create a 32-bit value in your source code. +# +# This will be an integer division of F_USB below, as it is sourced by +# F_USB after it has run through any CPU prescalers. Note that this value +# does not *change* the processor frequency - it should merely be updated to +# reflect the processor speed set externally so that the code can use accurate +# software delays. +F_CPU = 16000000 + + +# +# LUFA specific +# +# Target architecture (see library "Board Types" documentation). +ARCH = AVR8 + +# Input clock frequency. +# This will define a symbol, F_USB, in all source code files equal to the +# input clock frequency (before any prescaling is performed) in Hz. This value may +# differ from F_CPU if prescaling is used on the latter, and is required as the +# raw input clock is fed directly to the PLL sections of the AVR for high speed +# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' +# at the end, this will be done automatically to create a 32-bit value in your +# source code. +# +# If no clock division is performed on the input clock inside the AVR (via the +# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. +F_USB = $(F_CPU) + +# Interrupt driven control endpoint task(+60) +OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT + + +# Boot Section Size in *bytes* +# Teensy halfKay 512 +# Teensy++ halfKay 1024 +# Atmel DFU loader 4096 +# LUFA bootloader 4096 +# USBaspLoader 2048 +OPT_DEFS += -DBOOTLOADER_SIZE=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 ?= no # Enable keyboard backlight functionality on B7 by default +MIDI_ENABLE ?= no # MIDI controls +UNICODE_ENABLE ?= no # Unicode +BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID +AUDIO_ENABLE ?= no # Audio output on port C6 + +ifndef QUANTUM_DIR + include ../../Makefile +endif + + diff --git a/keyboards/maxipad/config.h b/keyboards/maxipad/config.h new file mode 100644 index 0000000000..59b8cebecd --- /dev/null +++ b/keyboards/maxipad/config.h @@ -0,0 +1,162 @@ +/* +Copyright 2012 Jun Wako + +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 . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6060 +#define DEVICE_VER 0x0001 +#define MANUFACTURER Wootpatoot +#define PRODUCT maxipad +#define DESCRIPTION g8ming keeb + +/* key matrix size */ +#define MATRIX_ROWS 5 +#define MATRIX_COLS 6 + +/* + * 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 { B6, F7, B2, B3, B1 } +#define MATRIX_COL_PINS { F6, C6, D7, F5, B4, B5 } +#define UNUSED_PINS + +/* COL2ROW or ROW2COL */ +#define DIODE_DIRECTION COL2ROW + +// #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 + +#endif diff --git a/keyboards/maxipad/keymaps/default/Makefile b/keyboards/maxipad/keymaps/default/Makefile new file mode 100644 index 0000000000..f4671a9d11 --- /dev/null +++ b/keyboards/maxipad/keymaps/default/Makefile @@ -0,0 +1,21 @@ +# Build Options +# change to "no" to disable the options, or define them in the Makefile in +# the appropriate keymap folder that will get included automatically +# +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 = no # Console for debug(+400) +COMMAND_ENABLE = yes # Commands for debug and configuration +NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work +BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality +MIDI_ENABLE = no # MIDI controls +AUDIO_ENABLE = no # Audio output on port C6 +UNICODE_ENABLE = no # Unicode +BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID +RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time. +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend + +ifndef QUANTUM_DIR + include ../../../../Makefile +endif \ No newline at end of file diff --git a/keyboards/maxipad/keymaps/default/config.h b/keyboards/maxipad/keymaps/default/config.h new file mode 100644 index 0000000000..df06a26206 --- /dev/null +++ b/keyboards/maxipad/keymaps/default/config.h @@ -0,0 +1,8 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +// place overrides here + +#endif \ No newline at end of file diff --git a/keyboards/maxipad/keymaps/default/keymap.c b/keyboards/maxipad/keymaps/default/keymap.c new file mode 100644 index 0000000000..7ca127fe4d --- /dev/null +++ b/keyboards/maxipad/keymaps/default/keymap.c @@ -0,0 +1,54 @@ +#include "maxipad.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { +[0] = KEYMAP( /* Base */ + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, \ + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, \ + MO(1), KC_A, KC_S, KC_D, KC_F, KC_G, \ + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, \ + KC_LCTL, KC_LALT, MO(1), KC_ENT,KC_GRV,KC_SPC \ +), +[1] = KEYMAP( + KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS \ +), +}; + +const uint16_t PROGMEM fn_actions[] = { + +}; + +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) { + return true; +} + +void led_set_user(uint8_t usb_led) { + +} \ No newline at end of file diff --git a/keyboards/maxipad/keymaps/default/readme.md b/keyboards/maxipad/keymaps/default/readme.md new file mode 100644 index 0000000000..a6c0d4a3f0 --- /dev/null +++ b/keyboards/maxipad/keymaps/default/readme.md @@ -0,0 +1 @@ +# The default keymap for maxipad \ No newline at end of file diff --git a/keyboards/maxipad/maxipad.c b/keyboards/maxipad/maxipad.c new file mode 100644 index 0000000000..879ae86a76 --- /dev/null +++ b/keyboards/maxipad/maxipad.c @@ -0,0 +1,28 @@ +#include "maxipad.h" + +void matrix_init_kb(void) { + // put your keyboard start-up code here + // runs once when the firmware starts up + + matrix_init_user(); +} + +void matrix_scan_kb(void) { + // put your looping keyboard code here + // runs every cycle (a lot) + + matrix_scan_user(); +} + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { + // put your per-action keyboard code here + // runs for every action, just before processing by the firmware + + 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); +} diff --git a/keyboards/maxipad/maxipad.h b/keyboards/maxipad/maxipad.h new file mode 100644 index 0000000000..eee1309ddc --- /dev/null +++ b/keyboards/maxipad/maxipad.h @@ -0,0 +1,25 @@ +#ifndef MAXIPAD_H +#define MAXIPAD_H + +#include "quantum.h" + +// 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 arguements +// The second converts the arguments into a two-dimensional array +#define KEYMAP( \ + k00, k01, k02, k03, k04, k05, \ + k10, k11, k12, k13, k14, k15, \ + k20, k21, k22, k23, k24, k25, \ + k30, k31, k32, k33, k34, k35, \ + k40, k41, k42, k43, k44, k45 \ +) \ +{ \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k40, k41, k42, k43, k44, k45} \ +} + +#endif diff --git a/keyboards/maxipad/readme.md b/keyboards/maxipad/readme.md new file mode 100644 index 0000000000..964212b8a6 --- /dev/null +++ b/keyboards/maxipad/readme.md @@ -0,0 +1,28 @@ +maxipad keyboard firmware +====================== + +## Quantum MK Firmware + +For the full Quantum feature list, see [the parent readme.md](/doc/readme.md). + +## Building + +Download or clone the whole firmware and navigate to the keyboards/maxipad 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`. + +### 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 `keymap` option like: + +``` +$ make keymap=[default|jack|] +``` + +Keymaps follow the format **__keymap.c__** and are stored in folders in the `keymaps` folder, eg `keymaps/my_keymap/` \ No newline at end of file From 79f82d3d80a24483d14b078d325bb0f45af58e3d Mon Sep 17 00:00:00 2001 From: climbalima Date: Thu, 10 Nov 2016 18:43:31 -0500 Subject: [PATCH 2/5] returned to o --- keyboards/lets_split/config.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/keyboards/lets_split/config.h b/keyboards/lets_split/config.h index bf618704cd..05439facb9 100644 --- a/keyboards/lets_split/config.h +++ b/keyboards/lets_split/config.h @@ -25,7 +25,7 @@ along with this program. If not, see . #define PRODUCT_ID 0x3060 #define DEVICE_VER 0x0001 #define MANUFACTURER Wootpatoot -#define PRODUCT Lets Split v2 +#define PRODUCT Lets Split #define DESCRIPTION A split keyboard for the cheap makers /* key matrix size */ @@ -34,8 +34,8 @@ along with this program. If not, see . #define MATRIX_COLS 6 // wiring of each half -#define MATRIX_ROW_PINS { D7, E6, B4, B5 } -#define MATRIX_COL_PINS { F6, F7, B1, B3, B2, B6 } +#define MATRIX_ROW_PINS { B5, B4, E6, D7 } +#define MATRIX_COL_PINS { F4, F5, F6, F7, B1, B3 } #define CATERINA_BOOTLOADER @@ -95,4 +95,4 @@ along with this program. If not, see . //#define NO_ACTION_MACRO //#define NO_ACTION_FUNCTION -#endif \ No newline at end of file +#endif From b5cecb4cc9df2d541050a9a95f48c1d5fb796ae4 Mon Sep 17 00:00:00 2001 From: climbalima Date: Thu, 10 Nov 2016 20:03:24 -0500 Subject: [PATCH 3/5] Added both revisions into one folder --- keyboards/lets_split/Makefile | 2 +- keyboards/lets_split/config.h | 16 ++- keyboards/lets_split/keymaps/default/keymap.c | 51 ++-------- keyboards/lets_split/lets_split.c | 27 ----- keyboards/lets_split/lets_split.h | 26 ++--- keyboards/lets_split/rev1/config.h | 98 +++++++++++++++++++ keyboards/lets_split/rev1/rev1.c | 30 ++++++ keyboards/lets_split/rev1/rev1.h | 25 +++++ keyboards/lets_split/rev2/config.h | 98 +++++++++++++++++++ keyboards/lets_split/rev2/rev2.c | 30 ++++++ keyboards/lets_split/rev2/rev2.h | 25 +++++ 11 files changed, 327 insertions(+), 101 deletions(-) create mode 100644 keyboards/lets_split/rev1/config.h create mode 100644 keyboards/lets_split/rev1/rev1.c create mode 100644 keyboards/lets_split/rev1/rev1.h create mode 100644 keyboards/lets_split/rev2/config.h create mode 100644 keyboards/lets_split/rev2/rev2.c create mode 100644 keyboards/lets_split/rev2/rev2.h diff --git a/keyboards/lets_split/Makefile b/keyboards/lets_split/Makefile index 982cfc591b..396d515553 100644 --- a/keyboards/lets_split/Makefile +++ b/keyboards/lets_split/Makefile @@ -72,7 +72,7 @@ USE_I2C ?= yes SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend CUSTOM_MATRIX = yes - +SUBPROJECT_DEFAULT = rev2 ifndef QUANTUM_DIR include ../../Makefile endif \ No newline at end of file diff --git a/keyboards/lets_split/config.h b/keyboards/lets_split/config.h index bf618704cd..245529ae08 100644 --- a/keyboards/lets_split/config.h +++ b/keyboards/lets_split/config.h @@ -28,15 +28,6 @@ along with this program. If not, see . #define PRODUCT Lets Split v2 #define DESCRIPTION A split keyboard for the cheap makers -/* key matrix size */ -// Rows are doubled-up -#define MATRIX_ROWS 8 -#define MATRIX_COLS 6 - -// wiring of each half -#define MATRIX_ROW_PINS { D7, E6, B4, B5 } -#define MATRIX_COL_PINS { F6, F7, B1, B3, B2, B6 } - #define CATERINA_BOOTLOADER // #define USE_I2C @@ -94,5 +85,10 @@ along with this program. If not, see . //#define NO_ACTION_ONESHOT //#define NO_ACTION_MACRO //#define NO_ACTION_FUNCTION - +#ifdef SUBPROJECT_rev1 + #include "rev1/config.h" +#endif +#ifdef SUBPROJECT_rev2 + #include "rev2/config.h" +#endif #endif \ No newline at end of file diff --git a/keyboards/lets_split/keymaps/default/keymap.c b/keyboards/lets_split/keymaps/default/keymap.c index 8c8466ebd5..d940638164 100644 --- a/keyboards/lets_split/keymaps/default/keymap.c +++ b/keyboards/lets_split/keymaps/default/keymap.c @@ -29,61 +29,24 @@ enum custom_keycodes { #define XXXXXXX KC_NO 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 | , | . | / |Enter | - * |------+------+------+------+------+------+------+------+------+------+------+------| - * |Adjust| Ctrl | Alt | GUI |Lower |Space |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, \ +[0] = KEYMAP( \ + KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, \ 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 , \ - KC_LCTL, _LOWER, KC_LGUI, KC_LALT, MO(_LOWER), KC_SPC, KC_LSFT, MO(_RAISE), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \ + KC_LCTL, _LOWER, KC_LGUI, KC_LALT, MO(_LOWER), KC_SPC, KC_SPC, MO(_RAISE), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \ ), - -[_LOWER] = KEYMAP( \ - KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC, \ +[3] = KEYMAP( \ + 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_BSPC, KC_BSPC, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \ ), - -/* Raise - * ,-----------------------------------------------------------------------------------. - * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp | - * |------+------+------+------+------+-------------+------+------+------+------+------| - * | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ | - * |------+------+------+------+------+------|------+------+------+------+------+------| - * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter | - * |------+------+------+------+------+------+------+------+------+------+------+------| - * | | | | | | | | Next | Vol- | Vol+ | Play | - * `-----------------------------------------------------------------------------------' - */ -[_RAISE] = KEYMAP( \ - KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, \ +[4] = KEYMAP( \ + 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_ENT, KC_ENT, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \ ), - -/* Adjust (Lower + Raise) - * ,-----------------------------------------------------------------------------------. - * | | Reset| | | | | | | | | | Del | - * |------+------+------+------+------+-------------+------+------+------+------+------| - * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak| | | - * |------+------+------+------+------+------|------+------+------+------+------+------| - * | | | | | | | | | | | | | - * |------+------+------+------+------+------+------+------+------+------+------+------| - * | | | | | | | | | | | | - * `-----------------------------------------------------------------------------------' - */ }; #ifdef AUDIO_ENABLE diff --git a/keyboards/lets_split/lets_split.c b/keyboards/lets_split/lets_split.c index 574c116a75..fe2d4bc193 100644 --- a/keyboards/lets_split/lets_split.c +++ b/keyboards/lets_split/lets_split.c @@ -1,30 +1,3 @@ #include "lets_split.h" -#ifdef AUDIO_ENABLE - float tone_startup[][2] = SONG(STARTUP_SOUND); - float tone_goodbye[][2] = SONG(GOODBYE_SOUND); -#endif -void matrix_init_kb(void) { - - #ifdef AUDIO_ENABLE - _delay_ms(20); // gets rid of tick - PLAY_NOTE_ARRAY(tone_startup, false, 0); - #endif - - // // green led on - // DDRD |= (1<<5); - // PORTD &= ~(1<<5); - - // // orange led on - // DDRB |= (1<<0); - // PORTB &= ~(1<<0); - - matrix_init_user(); -}; - -void shutdown_user(void) { - PLAY_NOTE_ARRAY(tone_goodbye, false, 0); - _delay_ms(150); - stop_all_notes(); -} diff --git a/keyboards/lets_split/lets_split.h b/keyboards/lets_split/lets_split.h index 04844ed639..2cdfb061f2 100644 --- a/keyboards/lets_split/lets_split.h +++ b/keyboards/lets_split/lets_split.h @@ -1,25 +1,13 @@ #ifndef LETS_SPLIT_H #define LETS_SPLIT_H +#ifdef SUBPROJECT_rev1 + #include "rev1.h" +#endif +#ifdef SUBPROJECT_rev2 + #include "rev2.h" +#endif + #include "quantum.h" -void promicro_bootloader_jmp(bool program); - -#define KEYMAP( \ - k00, k01, k02, k03, k04, k05, k45, k44, k43, k42, k41, k40, \ - k10, k11, k12, k13, k14, k15, k55, k54, k53, k52, k51, k50, \ - k20, k21, k22, k23, k24, k25, k65, k64, k63, k62, k61, k60, \ - k30, k31, k32, k33, k34, k35, k75, k74, k73, k72, k71, k70 \ - ) \ - { \ - { k00, k01, k02, k03, k04, k05 }, \ - { k10, k11, k12, k13, k14, k15 }, \ - { k20, k21, k22, k23, k24, k25 }, \ - { k30, k31, k32, k33, k34, k35 }, \ - { k40, k41, k42, k43, k44, k45 }, \ - { k50, k51, k52, k53, k54, k55 }, \ - { k60, k61, k62, k63, k64, k65 }, \ - { k70, k71, k72, k73, k74, k75 } \ - } - #endif \ No newline at end of file diff --git a/keyboards/lets_split/rev1/config.h b/keyboards/lets_split/rev1/config.h new file mode 100644 index 0000000000..b609ada077 --- /dev/null +++ b/keyboards/lets_split/rev1/config.h @@ -0,0 +1,98 @@ +/* +Copyright 2012 Jun Wako + +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 . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x3060 +#define DEVICE_VER 0x0001 +#define MANUFACTURER Wootpatoot +#define PRODUCT Lets Split v1 +#define DESCRIPTION A split keyboard for the cheap makers + +/* key matrix size */ +// Rows are doubled-up +#define MATRIX_ROWS 8 +#define MATRIX_COLS 6 + +// wiring of each half +#define MATRIX_ROW_PINS { B5, B4, E6, D7 } +#define MATRIX_COL_PINS { F4, F5, F6, F7, B1, B3 } + +#define CATERINA_BOOTLOADER + +// #define USE_I2C + +// #define EE_HANDS + +#define I2C_MASTER_LEFT +// #define I2C_MASTER_RIGHT + +/* COL2ROW or ROW2COL */ +#define DIODE_DIRECTION COL2ROW + +/* define if matrix has ghost */ +//#define MATRIX_HAS_GHOST + +/* number of backlight levels */ +// #define BACKLIGHT_LEVELS 3 + +/* Set 0 if debouncing isn't needed */ +#define DEBOUNCING_DELAY 5 + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +#define LOCKING_RESYNC_ENABLE + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* ws2812 RGB LED */ +#define ws2812_PORTREG PORTD +#define ws2812_DDRREG DDRD +#define ws2812_pin PD1 +#define RGBLED_NUM 28 // Number of LEDs +#define RGBLIGHT_HUE_STEP 10 +#define RGBLIGHT_SAT_STEP 17 +#define RGBLIGHT_VAL_STEP 17 + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +// #define NO_DEBUG + +/* disable print */ +// #define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION + +#endif \ No newline at end of file diff --git a/keyboards/lets_split/rev1/rev1.c b/keyboards/lets_split/rev1/rev1.c new file mode 100644 index 0000000000..574c116a75 --- /dev/null +++ b/keyboards/lets_split/rev1/rev1.c @@ -0,0 +1,30 @@ +#include "lets_split.h" + +#ifdef AUDIO_ENABLE + float tone_startup[][2] = SONG(STARTUP_SOUND); + float tone_goodbye[][2] = SONG(GOODBYE_SOUND); +#endif + +void matrix_init_kb(void) { + + #ifdef AUDIO_ENABLE + _delay_ms(20); // gets rid of tick + PLAY_NOTE_ARRAY(tone_startup, false, 0); + #endif + + // // green led on + // DDRD |= (1<<5); + // PORTD &= ~(1<<5); + + // // orange led on + // DDRB |= (1<<0); + // PORTB &= ~(1<<0); + + matrix_init_user(); +}; + +void shutdown_user(void) { + PLAY_NOTE_ARRAY(tone_goodbye, false, 0); + _delay_ms(150); + stop_all_notes(); +} diff --git a/keyboards/lets_split/rev1/rev1.h b/keyboards/lets_split/rev1/rev1.h new file mode 100644 index 0000000000..04fe0ddeb8 --- /dev/null +++ b/keyboards/lets_split/rev1/rev1.h @@ -0,0 +1,25 @@ +#ifndef REV1_H +#define REV1_H + +#include "quantum.h" + +void promicro_bootloader_jmp(bool program); + +#define KEYMAP( \ + k00, k01, k02, k03, k04, k05, k40, k41, k42, k43, k44, k45, \ + k10, k11, k12, k13, k14, k15, k50, k51, k52, k53, k54, k55, \ + k20, k21, k22, k23, k24, k25, k60, k61, k62, k63, k64, k65, \ + k30, k31, k32, k33, k34, k35, k70, k71, k72, k73, k74, k75 \ + ) \ + { \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k40, k41, k42, k43, k44, k45 }, \ + { k50, k51, k52, k53, k54, k55 }, \ + { k60, k61, k62, k63, k64, k65 }, \ + { k70, k71, k72, k73, k74, k75 } \ + } + +#endif \ No newline at end of file diff --git a/keyboards/lets_split/rev2/config.h b/keyboards/lets_split/rev2/config.h new file mode 100644 index 0000000000..bf618704cd --- /dev/null +++ b/keyboards/lets_split/rev2/config.h @@ -0,0 +1,98 @@ +/* +Copyright 2012 Jun Wako + +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 . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x3060 +#define DEVICE_VER 0x0001 +#define MANUFACTURER Wootpatoot +#define PRODUCT Lets Split v2 +#define DESCRIPTION A split keyboard for the cheap makers + +/* key matrix size */ +// Rows are doubled-up +#define MATRIX_ROWS 8 +#define MATRIX_COLS 6 + +// wiring of each half +#define MATRIX_ROW_PINS { D7, E6, B4, B5 } +#define MATRIX_COL_PINS { F6, F7, B1, B3, B2, B6 } + +#define CATERINA_BOOTLOADER + +// #define USE_I2C + +// #define EE_HANDS + +#define I2C_MASTER_LEFT +// #define I2C_MASTER_RIGHT + +/* COL2ROW or ROW2COL */ +#define DIODE_DIRECTION COL2ROW + +/* define if matrix has ghost */ +//#define MATRIX_HAS_GHOST + +/* number of backlight levels */ +// #define BACKLIGHT_LEVELS 3 + +/* Set 0 if debouncing isn't needed */ +#define DEBOUNCING_DELAY 5 + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +#define LOCKING_RESYNC_ENABLE + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* ws2812 RGB LED */ +#define ws2812_PORTREG PORTD +#define ws2812_DDRREG DDRD +#define ws2812_pin PD1 +#define RGBLED_NUM 28 // Number of LEDs +#define RGBLIGHT_HUE_STEP 10 +#define RGBLIGHT_SAT_STEP 17 +#define RGBLIGHT_VAL_STEP 17 + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +// #define NO_DEBUG + +/* disable print */ +// #define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION + +#endif \ No newline at end of file diff --git a/keyboards/lets_split/rev2/rev2.c b/keyboards/lets_split/rev2/rev2.c new file mode 100644 index 0000000000..574c116a75 --- /dev/null +++ b/keyboards/lets_split/rev2/rev2.c @@ -0,0 +1,30 @@ +#include "lets_split.h" + +#ifdef AUDIO_ENABLE + float tone_startup[][2] = SONG(STARTUP_SOUND); + float tone_goodbye[][2] = SONG(GOODBYE_SOUND); +#endif + +void matrix_init_kb(void) { + + #ifdef AUDIO_ENABLE + _delay_ms(20); // gets rid of tick + PLAY_NOTE_ARRAY(tone_startup, false, 0); + #endif + + // // green led on + // DDRD |= (1<<5); + // PORTD &= ~(1<<5); + + // // orange led on + // DDRB |= (1<<0); + // PORTB &= ~(1<<0); + + matrix_init_user(); +}; + +void shutdown_user(void) { + PLAY_NOTE_ARRAY(tone_goodbye, false, 0); + _delay_ms(150); + stop_all_notes(); +} diff --git a/keyboards/lets_split/rev2/rev2.h b/keyboards/lets_split/rev2/rev2.h new file mode 100644 index 0000000000..2a2246f056 --- /dev/null +++ b/keyboards/lets_split/rev2/rev2.h @@ -0,0 +1,25 @@ +#ifndef REV2_H +#define REV2_H + +#include "quantum.h" + +void promicro_bootloader_jmp(bool program); + +#define KEYMAP( \ + k00, k01, k02, k03, k04, k05, k45, k44, k43, k42, k41, k40, \ + k10, k11, k12, k13, k14, k15, k55, k54, k53, k52, k51, k50, \ + k20, k21, k22, k23, k24, k25, k65, k64, k63, k62, k61, k60, \ + k30, k31, k32, k33, k34, k35, k75, k74, k73, k72, k71, k70 \ + ) \ + { \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k40, k41, k42, k43, k44, k45 }, \ + { k50, k51, k52, k53, k54, k55 }, \ + { k60, k61, k62, k63, k64, k65 }, \ + { k70, k71, k72, k73, k74, k75 } \ + } + +#endif \ No newline at end of file From dd22c787b8b417df109d2136c76ce496dd7b93e3 Mon Sep 17 00:00:00 2001 From: climbalima Date: Mon, 14 Nov 2016 23:05:37 -0500 Subject: [PATCH 4/5] fixed extra paste --- keyboards/lets_split/config.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/keyboards/lets_split/config.h b/keyboards/lets_split/config.h index a5394c5e4d..bf04731162 100644 --- a/keyboards/lets_split/config.h +++ b/keyboards/lets_split/config.h @@ -105,7 +105,6 @@ along with this program. If not, see . #include "rev2/config.h" #endif #endif -======= -#endif ->>>>>>> 79f82d3d80a24483d14b078d325bb0f45af58e3d + + From bce6e52391da7c5f620c96a91857940f0dee19df Mon Sep 17 00:00:00 2001 From: climbalima Date: Mon, 14 Nov 2016 23:08:10 -0500 Subject: [PATCH 5/5] fixed conflict --- keyboards/lets_split/config.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/keyboards/lets_split/config.h b/keyboards/lets_split/config.h index bf04731162..059d45b0c0 100644 --- a/keyboards/lets_split/config.h +++ b/keyboards/lets_split/config.h @@ -28,8 +28,6 @@ along with this program. If not, see . #define PRODUCT Lets Split #define DESCRIPTION A split keyboard for the cheap makers -<<<<<<< HEAD -======= /* key matrix size */ // Rows are doubled-up #define MATRIX_ROWS 8 @@ -39,7 +37,6 @@ along with this program. If not, see . #define MATRIX_ROW_PINS { B5, B4, E6, D7 } #define MATRIX_COL_PINS { F4, F5, F6, F7, B1, B3 } ->>>>>>> 79f82d3d80a24483d14b078d325bb0f45af58e3d #define CATERINA_BOOTLOADER // #define USE_I2C