diff options
author | Jack Humbert <jack.humb@gmail.com> | 2019-01-10 17:26:40 +0100 |
---|---|---|
committer | MechMerlin <30334081+mechmerlin@users.noreply.github.com> | 2019-01-10 17:26:40 +0100 |
commit | d28684da90536b54ff7d145decb80e0bd9290996 (patch) | |
tree | 5e7607561b8440ae3f1d078c9d00bdcdfbdd653b | |
parent | 3cf179be61a10860b2b66aecf2ec5ca6f0e30605 (diff) | |
download | qmk_firmware-d28684da90536b54ff7d145decb80e0bd9290996.tar.gz qmk_firmware-d28684da90536b54ff7d145decb80e0bd9290996.tar.xz |
Adds support for JacoBurge's TouchPad (#4186)
* add touchpad
* progress
* working with leds and vibrations
* adds readme
* Update keyboards/touchpad/readme.md
Co-Authored-By: jackhumbert <jack.humb@gmail.com>
* updates
-rwxr-xr-x | drivers/avr/i2c_master.c | 5 | ||||
-rw-r--r-- | keyboards/touchpad/config.h | 70 | ||||
-rw-r--r-- | keyboards/touchpad/keymaps/default/keymap.c | 30 | ||||
-rw-r--r-- | keyboards/touchpad/matrix.c | 291 | ||||
-rw-r--r-- | keyboards/touchpad/readme.md | 15 | ||||
-rw-r--r-- | keyboards/touchpad/rules.mk | 67 | ||||
-rw-r--r-- | keyboards/touchpad/touchpad.c | 1 | ||||
-rw-r--r-- | keyboards/touchpad/touchpad.h | 2 |
8 files changed, 480 insertions, 1 deletions
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c index a04e6570d..19bae33e9 100755 --- a/drivers/avr/i2c_master.c +++ b/drivers/avr/i2c_master.c @@ -179,6 +179,9 @@ i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16 status = i2c_write(regaddr, timeout); if (status) return status; + status = i2c_stop(timeout); + if (status) return status; + status = i2c_start(devaddr | 0x01, timeout); if (status) return status; @@ -217,4 +220,4 @@ i2c_status_t i2c_stop(uint16_t timeout) } return I2C_STATUS_SUCCESS; -}
\ No newline at end of file +} diff --git a/keyboards/touchpad/config.h b/keyboards/touchpad/config.h new file mode 100644 index 000000000..8d34daae1 --- /dev/null +++ b/keyboards/touchpad/config.h @@ -0,0 +1,70 @@ +/* +Copyright 2018 Jack Humbert <jack.humb@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0x16D0 +#define PRODUCT_ID 0x0DB8 +#define DEVICE_VER 0x0001 +#define MANUFACTURER JacoBurge +#define PRODUCT TouchPad +#define DESCRIPTION A capacitive touchpad + +/* key matrix size */ +#define MATRIX_ROWS 6 +#define MATRIX_COLS 6 + + +/* 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)) \ +) + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +//#define NO_DEBUG + +/* disable print */ +//#define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION diff --git a/keyboards/touchpad/keymaps/default/keymap.c b/keyboards/touchpad/keymaps/default/keymap.c new file mode 100644 index 000000000..92f772aaa --- /dev/null +++ b/keyboards/touchpad/keymaps/default/keymap.c @@ -0,0 +1,30 @@ +/* Copyright 2018 Jack Humbert <jack.humb@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + +[0] = { + { KC_A, KC_B, KC_C, KC_D, KC_E, KC_F }, + { KC_A, KC_B, KC_C, KC_D, KC_E, KC_F }, + { KC_A, KC_B, KC_C, KC_D, KC_E, KC_F }, + { KC_A, KC_B, KC_C, KC_D, KC_E, KC_F }, + { KC_A, KC_B, KC_C, KC_D, KC_E, KC_F }, + { KC_A, KC_B, KC_C, KC_D, KC_E, KC_F } +} + +}; diff --git a/keyboards/touchpad/matrix.c b/keyboards/touchpad/matrix.c new file mode 100644 index 000000000..3af4c5c3c --- /dev/null +++ b/keyboards/touchpad/matrix.c @@ -0,0 +1,291 @@ +/* +MIT License +Copyright (c) 2018, JacoBurge +Adapted for QMK by Jack Humbert in 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "matrix.h" +#include "i2c_master.h" +#include "quantum.h" + +#define VIBRATE_LENGTH 50 //Defines number of interrupts motor will vibrate for, must be bigger than 8 for correct operation +volatile uint8_t vibrate = 0; //Trigger vibration in interrupt + +static matrix_row_t matrix[MATRIX_ROWS]; + +const uint8_t SENr[6] = {1, 2, 3, 5, 6, 7};//Maps capacitive pads to pins +const uint8_t SENc[6] = {0, 4, 8, 9, 10, 11}; + +volatile uint8_t LEDs[6][6] = {{0}};//Stores current LED values + +//Read data from the cap touch IC +uint8_t readDataFromTS(uint8_t reg) { + uint8_t rx[1] = { 0 }; + if (i2c_readReg(0x1C << 1, reg, rx, 1, 100) == 0) { + return rx[0]; + } + return 0; +} + +//Write data to cap touch IC +uint8_t writeDataToTS(uint8_t reg, uint8_t data) { + uint8_t tx[2] = { reg, data }; + if (i2c_transmit(0x1C << 1, tx, 2, 100) == 0) { + return 1; + } else { + return 0; + } +} + + +uint8_t checkTSPres(void) { + return (readDataFromTS(0x00) == 0x3E); +} + +uint8_t capSetup(void) { + + uint8_t temp_return = checkTSPres(); + + if (temp_return == 1) { + // Perform measurements every 16ms + writeDataToTS(0x08, 1); + + // Increase detection integrator value + writeDataToTS(0x0B, 1); + + // Oversample to gain two bits for columns + writeDataToTS(0x28, 0x42); + writeDataToTS(0x29, 0x00); + writeDataToTS(0x2A, 0x00); + writeDataToTS(0x2B, 0x00); + writeDataToTS(0x2C, 0x42); + writeDataToTS(0x2D, 0x00); + writeDataToTS(0x2E, 0x00); + writeDataToTS(0x2F, 0x00); + writeDataToTS(0x30, 0x42); + writeDataToTS(0x31, 0x42); + writeDataToTS(0x32, 0x42); + writeDataToTS(0x33, 0x42); + + // Recalibration if touch detected for more than 8 seconds n*0.16s + writeDataToTS(0x0C, 50); + + // Enable keys and set key groups + writeDataToTS(0x1C, 0x00 | 0x04); + writeDataToTS(0x1D, 0x00 | 0x08); + writeDataToTS(0x1E, 0x00 | 0x08); + writeDataToTS(0x1F, 0x00 | 0x08); + writeDataToTS(0x20, 0x00 | 0x04); + writeDataToTS(0x21, 0x00 | 0x08); + writeDataToTS(0x22, 0x00 | 0x08); + writeDataToTS(0x23, 0x00 | 0x08); + writeDataToTS(0x24, 0x00 | 0x04); + writeDataToTS(0x25, 0x00 | 0x04); + writeDataToTS(0x26, 0x00 | 0x04); + writeDataToTS(0x27, 0x00 | 0x04); + + } + return temp_return; +} + +__attribute__ ((weak)) +void matrix_init_user(void) {} + +__attribute__ ((weak)) +void matrix_scan_user(void) {} + +__attribute__ ((weak)) +void matrix_init_kb(void) { + matrix_init_user(); +} + +__attribute__ ((weak)) +void matrix_scan_kb(void) { + matrix_scan_user(); +} + +void matrix_init(void) { + + i2c_init(); + + //Motor enable + setPinOutput(E6); + //Motor PWM + setPinOutput(D7); + + //Power LED + setPinOutput(B7); + writePinHigh(B7); + + //LEDs Columns + setPinOutput(F7); + setPinOutput(F6); + setPinOutput(F5); + setPinOutput(F4); + setPinOutput(F1); + setPinOutput(F0); + + //LEDs Rows + setPinOutput(D6); + setPinOutput(B4); + setPinOutput(B5); + setPinOutput(B6); + setPinOutput(C6); + setPinOutput(C7); + + //Capacitive Interrupt + setPinInput(D2); + + capSetup(); + writeDataToTS(0x06, 0x12); //Calibrate capacitive touch IC + + memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); + + matrix_init_quantum(); +} + + +uint16_t touchDetectionRoutine(void) { + uint16_t data; + uint8_t temp1, temp2; + + temp1 = readDataFromTS(0x04); + temp2 = readDataFromTS(0x03); + data = temp1; + data = (data << 8) | temp2; + return data; + +} + +//Process raw capacitive data, map pins to rows and columns +void decodeArray(uint16_t dataIn, uint8_t *column, uint8_t *row) { + uint8_t i1 = 20, i2 = 20; + for (uint8_t i = 0; i < 12; i++) { + if ((dataIn & 0b1) == 1) { + if (i1 == 20) { + i1 = i; + } else if (i2 == 20) { + i2 = i; + } + } + dataIn = dataIn >> 1; + } + + for (uint8_t j = 0; j < 6; j++) { + if (SENr[j] == i1 || SENr[j] == i2) { + *row = j; + } + if (SENc[j] == i1 || SENc[j] == i2) { + *column = j; + } + } +} + +void touchClearCurrentDetections(void) { + readDataFromTS(0x05); + readDataFromTS(0x02); + readDataFromTS(0x03); + readDataFromTS(0x04); +} + +//Check interrupt pin +uint8_t isTouchChangeDetected(void) { + return !readPin(D2); +} + +uint8_t matrix_scan(void) { + if (isTouchChangeDetected()) { + uint16_t dataIn = touchDetectionRoutine(); + if ((dataIn & 0b111100010001) > 0 && (dataIn & 0b000011101110) > 0) { + uint8_t column = 10, row = 10; + decodeArray(dataIn, &column, &row); + if (column != 10 && row != 10) { + vibrate = VIBRATE_LENGTH; //Trigger vibration + matrix[row] = _BV(column); + } else { + memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); + } + } else { + memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); + } + touchClearCurrentDetections(); + } + + for (uint8_t c = 0; c < 6; c++) { + for (uint8_t r = 0; r < 6; r++) { + switch (r) { + case 0: writePin(D6, matrix_is_on(r, c)); break; + case 1: writePin(B4, matrix_is_on(r, c)); break; + case 2: writePin(B5, matrix_is_on(r, c)); break; + case 3: writePin(B6, matrix_is_on(r, c)); break; + case 4: writePin(C6, matrix_is_on(r, c)); break; + case 5: writePin(C7, matrix_is_on(r, c)); break; + } + + switch (c) { + case 0: writePin(F5, !matrix_is_on(r, c)); break; + case 1: writePin(F4, !matrix_is_on(r, c)); break; + case 2: writePin(F1, !matrix_is_on(r, c)); break; + case 3: writePin(F0, !matrix_is_on(r, c)); break; + case 4: writePin(F6, !matrix_is_on(r, c)); break; + case 5: writePin(F7, !matrix_is_on(r, c)); break; + } + } + } + + if (vibrate == VIBRATE_LENGTH) { + writePinHigh(E6); + writePinHigh(D7); + vibrate--; + } else if (vibrate > 0) { + vibrate--; + } else if (vibrate == 0) { + writePinLow(D7); + writePinLow(E6); + } + + matrix_scan_quantum(); + + return 1; + +} + +bool matrix_is_on(uint8_t row, uint8_t col) { + return (matrix[row] & (1<<col)); +} + +matrix_row_t matrix_get_row(uint8_t row) { + return matrix[row]; +} + +void matrix_print(void) { + printf("\nr/c 01234567\n"); + for (uint8_t row = 0; row < MATRIX_ROWS; row++) { + printf("%X0: ", row); + matrix_row_t data = matrix_get_row(row); + for (int col = 0; col < MATRIX_COLS; col++) { + if (data & (1<<col)) + printf("1"); + else + printf("0"); + } + printf("\n"); + } +} diff --git a/keyboards/touchpad/readme.md b/keyboards/touchpad/readme.md new file mode 100644 index 000000000..f80bfa87b --- /dev/null +++ b/keyboards/touchpad/readme.md @@ -0,0 +1,15 @@ +# Touchpad + +![TouchPad](https://static1.squarespace.com/static/561b7180e4b05a82a1747f0b/59d8985903596eb5953e1803/5a43f205e4966b67c55878a2/1521104083905/IMG_2183.jpg?format=2500w) + +A small capacitive 6x6 touchpad for launching programs. [More info](https://jacoburge.co.uk/touch-pad/) + +Keyboard Maintainer: QMK Community +Hardware Supported: TouchPad PCB +Hardware Availability: [JaboBurge's Shop](https://jacoburge.co.uk/shop) + +Make example for this keyboard (after setting up your build environment): + + make touchpad:default + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). diff --git a/keyboards/touchpad/rules.mk b/keyboards/touchpad/rules.mk new file mode 100644 index 000000000..e4fa2ac13 --- /dev/null +++ b/keyboards/touchpad/rules.mk @@ -0,0 +1,67 @@ +# MCU name +MCU = atmega32u4 + +SRC = matrix.c i2c_master.c + +# 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) + +# Bootloader +# This definition is optional, and if your keyboard supports multiple bootloaders of +# different sizes, comment this out, and the correct address will be loaded +# automatically (+60). See bootloader.mk for all options. +BOOTLOADER = caterina + +# Interrupt driven control endpoint task(+60) +OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT + +# 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 = no # Mouse keys(+4700) +EXTRAKEY_ENABLE = yes # Audio control and System control(+450) +CONSOLE_ENABLE = yes # Console for debug(+400) +COMMAND_ENABLE = no # 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. +API_SYSEX_ENABLE = no +CUSTOM_MATRIX = 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/touchpad/touchpad.c b/keyboards/touchpad/touchpad.c new file mode 100644 index 000000000..fe96d56b6 --- /dev/null +++ b/keyboards/touchpad/touchpad.c @@ -0,0 +1 @@ +#include "touchpad.h" diff --git a/keyboards/touchpad/touchpad.h b/keyboards/touchpad/touchpad.h new file mode 100644 index 000000000..010d4b138 --- /dev/null +++ b/keyboards/touchpad/touchpad.h @@ -0,0 +1,2 @@ +#pragma once +#include "quantum.h" |