From ed98250e62d9e37218931d09a4216ffe09d3ce3a Mon Sep 17 00:00:00 2001 From: Maarten Dekkers Date: Thu, 12 Jul 2018 21:42:36 +0200 Subject: [PATCH] Add kmini (#3386) * Add kmini * Change keyboard USB description --- keyboards/kmini/config.h | 58 +++++ keyboards/kmini/info.json | 6 + keyboards/kmini/keymaps/default/keymap.c | 60 +++++ keyboards/kmini/kmini.c | 53 ++++ keyboards/kmini/kmini.h | 36 +++ keyboards/kmini/matrix.c | 303 +++++++++++++++++++++++ keyboards/kmini/readme.md | 13 + keyboards/kmini/rules.mk | 71 ++++++ 8 files changed, 600 insertions(+) create mode 100755 keyboards/kmini/config.h create mode 100755 keyboards/kmini/info.json create mode 100755 keyboards/kmini/keymaps/default/keymap.c create mode 100755 keyboards/kmini/kmini.c create mode 100755 keyboards/kmini/kmini.h create mode 100755 keyboards/kmini/matrix.c create mode 100755 keyboards/kmini/readme.md create mode 100755 keyboards/kmini/rules.mk diff --git a/keyboards/kmini/config.h b/keyboards/kmini/config.h new file mode 100755 index 0000000000..567a754429 --- /dev/null +++ b/keyboards/kmini/config.h @@ -0,0 +1,58 @@ +/* Copyright 2018 Maarten Dekkers + * + * 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 0x6050 +#define DEVICE_VER 0x0104 +#define MANUFACTURER Revo +#define PRODUCT KMAC Kmini +#define DESCRIPTION QMK keyboard firmware for Revo KMAC Mini + +/* key matrix size */ +#define MATRIX_ROWS 5 +#define MATRIX_COLS 17 + +/* + * Keyboard Matrix Assignments + * The KMAC uses a demultiplexer for some of the cols. + * See matrix.c for more details. +*/ +#define MATRIX_ROW_PINS { D0, D1, D2, D3, D5 } +#define MATRIX_COL_PINS { } +#define UNUSED_PINS + +/* COL2ROW, ROW2COL, or CUSTOM_MATRIX */ +#define DIODE_DIRECTION CUSTOM_MATRIX + +/* number of backlight levels */ +#define BACKLIGHT_LEVELS 3 +// #define BACKLIGHT_PIN B7 +// #define BACKLIGHT_BREATHING + +/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ +#define DEBOUNCING_DELAY 5 + +/* key combination for magic key command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +#endif diff --git a/keyboards/kmini/info.json b/keyboards/kmini/info.json new file mode 100755 index 0000000000..e5631f9334 --- /dev/null +++ b/keyboards/kmini/info.json @@ -0,0 +1,6 @@ +{ + "keyboard_name": "KMAC Mini", + "url": "http://kbdmodadmin.cafe24.com/product/detail.html?product_no=12&cate_no=4&display_group=1", + "maintainer": "maartenwut" + } +} diff --git a/keyboards/kmini/keymaps/default/keymap.c b/keyboards/kmini/keymaps/default/keymap.c new file mode 100755 index 0000000000..73d9b611e3 --- /dev/null +++ b/keyboards/kmini/keymaps/default/keymap.c @@ -0,0 +1,60 @@ +/* Copyright 2018 Maarten Dekkers + * + * 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 . + */ +#include "kmini.h" + +// Helpful defines +#define _____ KC_TRNS + +// Each layer gets a name for readability, which is then used in the keymap matrix below. +// The underscores don't mean anything - you can have a layer called STUFF or any other name. +// Layer names don't all need to be of the same length, obviously, and you can also skip them +// entirely and just use numbers. +#define _MA 0 +#define _FN 1 + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_MA] = LAYOUT( + KC_F1, KC_F2, KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, \ + KC_F3, KC_F4, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, \ + KC_F5, KC_F6, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP, \ + KC_F7, KC_F8, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN, \ + KC_F9, KC_F10, KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, MO(_FN), KC_LEFT, KC_DOWN, KC_RGHT \ + ), + [_FN] = LAYOUT( + _____, _____, _____, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, RESET, _____, \ + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, \ + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, \ + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, \ + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____ \ + ), +}; + +void led_set_user(uint8_t usb_led) { + if (usb_led & (1< + * + * 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 . + */ +#include "kmini.h" + +void matrix_init_kb(void) { + // put your keyboard start-up code here + // runs once when the firmware starts up + led_init_ports(); + 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_init_ports(void) { + DDRB |= (1<<1); // OUT + DDRB |= (1<<2); // OUT + DDRB |= (1<<3); // OUT +} + +/* LED pin configuration + * Caps Lock: Low B1 + * Side1: Low B3 + * Side2: Low B2 + */ +void led_set_kb(uint8_t usb_led) { + led_set_user(usb_led); +} + diff --git a/keyboards/kmini/kmini.h b/keyboards/kmini/kmini.h new file mode 100755 index 0000000000..0576425ead --- /dev/null +++ b/keyboards/kmini/kmini.h @@ -0,0 +1,36 @@ +/* Copyright 2018 Maarten Dekkers + * + * 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 KMINI_H +#define KMINI_H +#define ___ KC_NO + +#include "quantum.h" + +#define LAYOUT( \ + K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, K0F, K0G, \ + K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, K1F, K1G, \ + K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, K2F, K2G, \ + K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3E, K3F, K3G, \ + K40, K41, K42, K43, K44, K47, K4C, K4E, K4F, K4G \ +) { \ + {K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, K0F, K0G}, \ + {K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, K1F, K1G}, \ + {K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, ___, K2F, K2G}, \ + {K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, ___, K3E, K3F, K3G}, \ + {K40, K41, K42, K43, K44, ___, ___, K47, ___, ___, ___, ___, K4C, ___, K4E, K4F, K4G}, \ +} + +#endif diff --git a/keyboards/kmini/matrix.c b/keyboards/kmini/matrix.c new file mode 100755 index 0000000000..f0733340ce --- /dev/null +++ b/keyboards/kmini/matrix.c @@ -0,0 +1,303 @@ +/* Copyright 2018 Maarten Dekkers + * + * 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 . + */ +#include +#include +#if defined(__AVR__) +#include +#endif +#include "wait.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "matrix.h" +#include "timer.h" + + +/* Set 0 if debouncing isn't needed */ +#ifndef DEBOUNCING_DELAY +# define DEBOUNCING_DELAY 5 +#endif + +#define COL_SHIFTER ((uint32_t)1) + +static uint16_t debouncing_time; +static bool debouncing = false; + + +static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_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 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); + +inline +uint8_t matrix_rows(void) { + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) { + return MATRIX_COLS; +} + +void matrix_init(void) { + unselect_cols(); + init_rows(); + + // 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++) { + bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col); + if (matrix_changed) { + debouncing = true; + debouncing_time = timer_read(); + } + } + + if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + matrix[i] = matrix_debouncing[i]; + } + debouncing = false; + } + + matrix_scan_quantum(); + return 1; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & ((matrix_row_t)1> 4) & _BV(E2 & 0xF)) == 0) + { + // Pin LO, set col bit + current_matrix[row_index] |= (COL_SHIFTER << current_col); + } + else + { + // Pin HI, clear col bit + current_matrix[row_index] &= ~(COL_SHIFTER << current_col); + } + } + else { + if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF))) + { + // Pin HI, set col bit + current_matrix[row_index] |= (COL_SHIFTER << current_col); + } + else + { + // Pin LO, clear col bit + current_matrix[row_index] &= ~(COL_SHIFTER << current_col); + } + } + + // Determine if the matrix changed state + if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) + { + matrix_changed = true; + } + } + + // Unselect cols + unselect_cols(); + + return matrix_changed; +} + +/* Row pin configuration + * row: 0 1 2 3 4 + * pin: D0 D1 D2 D3 D5 + * + * Caps lock uses its own pin E2 + */ +static void init_rows(void) { + DDRD &= ~((1<<0)| (1<<1) | (1<<2) | (1<<3) | (1<<5)); // IN + PORTD &= ~((1<<0)| (1<<1) | (1<<2) | (1<<3) | (1<<5)); // LO + + DDRE &= ~(1<<2); // IN + PORTE |= (1<<2); // HI +} + +/* Columns 0 - 16 + * col 0: B5 + * col 1: B6 + * These columns use a 74HC237D 3 to 8 bit demultiplexer. + * A B C GL1 + * col / pin: PF0 PF1 PC7 PC6 + * 2: 0 0 0 1 + * 3: 1 0 0 1 + * 4: 0 1 0 1 + * 5: 1 1 0 1 + * 6: 0 0 1 1 + * 7: 1 0 1 1 + * 8: 0 1 1 1 + * 9: 1 1 1 1 + * col 10: E6 + * col 11: B0 + * col 12: B7 + * col 13: D4 + * col 14: D6 + * col 15: D7 + * col 16: B4 + */ +static void unselect_cols(void) { + DDRB |= (1<<5) | (1<<6) | (1<<0) | (1<<7) | (1<<4); // OUT + PORTB &= ~((1<<5) | (1<<6) | (1<<0) | (1<<7) | (1<<4)); // LO + + DDRD |= (1<<4) | (1<<6) | (1<<7); // OUT + PORTD &= ~((1<<4) | (1<<6) | (1<<7)); // LO + + DDRE |= (1<<6); // OUT + PORTE &= ~((1<<6)); // LO + + DDRF |= (1<<0) | (1<<1); // OUT + PORTF &= ~((1<<0) | (1<<1)); // LO + + DDRC |= (1<<7) | (1<<6); // OUT + PORTC &= ~((1<<7) | (1<<6)); // LO +} + +static void select_col(uint8_t col) +{ + switch (col) { + case 0: + PORTB |= (1<<5); // HI + break; + case 1: + PORTB |= (1<<6); // HI + break; + case 2: + PORTC |= (1<<6); // HI + break; + case 3: + PORTC |= (1<<6); // HI + PORTF |= (1<<0); // HI + break; + case 4: + PORTC |= (1<<6); // HI + PORTF |= (1<<1); // HI + break; + case 5: + PORTC |= (1<<6); // HI + PORTF |= (1<<0); // HI + PORTF |= (1<<1); // HI + break; + case 6: + PORTC |= (1<<6); // HI + PORTC |= (1<<7); // HI + break; + case 7: + PORTC |= (1<<6); // HI + PORTF |= (1<<0); // HI + PORTC |= (1<<7); // HI + break; + case 8: + PORTC |= (1<<6); // HI + PORTF |= (1<<1); // HI + PORTC |= (1<<7); // HI + break; + case 9: + PORTC |= (1<<6); // HI + PORTF |= (1<<0); // HI + PORTF |= (1<<1); // HI + PORTC |= (1<<7); // HI + break; + case 10: + PORTE |= (1<<6); // HI + break; + case 11: + PORTB |= (1<<0); // HI + break; + case 12: + PORTB |= (1<<7); // HI + break; + case 13: + PORTD |= (1<<4); // HI + break; + case 14: + PORTD |= (1<<6); // HI + break; + case 15: + PORTD |= (1<<7); // HI + break; + case 16: + PORTB |= (1<<4); // HI + break; + } +} diff --git a/keyboards/kmini/readme.md b/keyboards/kmini/readme.md new file mode 100755 index 0000000000..2a9e8e7908 --- /dev/null +++ b/keyboards/kmini/readme.md @@ -0,0 +1,13 @@ +Kmini keyboard firmware +====================== + +The Revo Kmini is a 65% keyboard with an additional two columns on the left. It is programmed with the 'KMAC key map', which only works on Windows and according to a [user](https://www.keebtalk.com/t/programming-revo-kmini/2107/7) it cannot map media controls or change the capslock key. + +## Hardware +Columns 0, 1 and 10-16 and rows 0-4 are wired directly to the ATmega32u4, and columns 2-9 are wired to the [74HC237D demultiplexer](https://www.mouser.de/datasheet/2/916/74HC237-1319445.pdf). Capslock is on E2 and also triggers a reset if held when plugging the cable in. There are three possible places for leds, which are the capslock key and the two keys above the right arrow key. All three of them are individually controllable. The ATmega32u4 runs on an external crystal on 8mhz, so you'll have to change the bitclock on the ISP programmer if you're unable to read or write the chip. + +## How to build +Please read the [documentation](https://docs.qmk.fm). + +## How to flash +Hold the capslock key while plugging in the USB and flash the .hex file using QMK Toolbox or Atmel FLIP. \ No newline at end of file diff --git a/keyboards/kmini/rules.mk b/keyboards/kmini/rules.mk new file mode 100755 index 0000000000..a4183870ca --- /dev/null +++ b/keyboards/kmini/rules.mk @@ -0,0 +1,71 @@ +# Project specific files +SRC = matrix.c + +# MCU name +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 = 8000000 + + +# +# 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 yes to no to disable +# +BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) +MOUSEKEY_ENABLE = yes # Mouse keys(+4700) +EXTRAKEY_ENABLE = yes # Audio control and System control(+450) +CONSOLE_ENABLE = no # Console for debug(+400) +COMMAND_ENABLE = yes # Commands for debug and configuration +CUSTOM_MATRIX = yes # Custom matrix file +# 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 = yes # USB Nkey Rollover +BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality +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 +FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches