Compare commits

...

20 Commits

Author SHA1 Message Date
just-another-jxliu
99d89b124f Drop FW Fixes for massdrop alt, ctrl, rocketeer & shift keyboards (#8)
- In config.h of each, added '#define BOOTKEY_HOLD_MS  2000' to define hold time required to active Boot key (was 500ms hardcode)
- Updated all active keymap.c files to use this define
- Added line in quantum.c in MAGIC_TOGGLE_NKRO case to clear_keyboard() before toggling nkro state to fix stuck key issues when switching NKRO.
2019-08-15 00:51:54 -07:00
just-another-jxliu
8b5e4959a0 Update SHIFT and Rocketeer config_led.c (#7) 2019-08-05 07:01:08 -07:00
just-another-jxliu
3cb242b47d Change debounce methodology to shift debounce window until row is settled (#5) 2019-08-02 16:44:19 -07:00
jonathan.liu
9b80ceca52 Rocketeer: LED positions for bottom LEDs, update mac_md keymap 2019-07-16 08:47:51 -07:00
jonathan.liu
9fdfae83d1 Misc including Rocketeer config_led.c 2019-07-12 03:05:12 -07:00
jonathan.liu
9075995ea3 Merge remote-tracking branch 'upstream/master' 2019-07-12 03:04:30 -07:00
jonathan.liu
c529972416 Merge remote-tracking branch 'origin/md_1800_qmk' 2019-07-12 00:49:08 -07:00
jonathan.liu
4c6b0f0291 Merge commit 'd0fb7005d51be7c876e63e87778d080c8a733a13' 2019-07-12 00:47:55 -07:00
jonathan.liu
9352fbee07 Merge commit '5fcd744ddba591829a129560992b2e43fb615d4d' 2019-07-11 23:47:27 -07:00
jonathan.liu
441b212c86 Upstream merge up to 02d44beb44 2019-07-11 23:21:18 -07:00
patrickmt
413a8938f1 190528 updates to get it compiling
Updates to get the package compiling and working for the most part
Bug with reactive lighting for QMK code and keeping caps/num lock lit when on
2019-06-03 10:30:35 -04:00
patrickmt
082c835c26 Merge remote-tracking branch 'upstream/master' into md_1800_qmk 2019-04-16 09:26:22 -04:00
patrickmt
0500497612 ctrl alt working but not fully tested 2019-04-16 09:24:38 -04:00
jonathan.liu
a0fac849eb Merge remote-tracking branch 'upstream/master' 2018-12-06 23:35:20 -08:00
jonathan.liu
e0e57110e0 Add LED instructions to ALT default/mac, CTRL mac 2018-10-17 11:43:40 -07:00
jonathan.liu
02d6be34d7 Merge remote-tracking branch 'upstream/master' 2018-10-15 17:42:39 -07:00
jonathan.liu
151feb4723 Change back to LED IDs starting at 1 2018-09-28 17:54:08 -07:00
jonathan.liu
ca618bcf6c CTRL: LED loop perf improvement from patrickmt 2018-09-20 19:02:39 -07:00
jonathan.liu
d8936f3435 Use highest active layer only for LEDs 2018-09-14 15:47:47 -07:00
just-another-jxliu
5fb9b45481 CTRL (arm_atsam) support user-defined LED instructions (#2)
* CTRL (arm_atsam) support user-defined LED instructions

* ok, layer matching works now

* Bitwise LED ID to reduce number of instructions (performance)

* Use 32-bit ints to be more compatible with generation in JS

* TYpo
2018-09-14 14:23:36 -07:00
90 changed files with 6330 additions and 851 deletions

View File

@@ -0,0 +1,216 @@
/*
* Good on you for modifying your layout, this is the most nonQMK layout you will come across
* There are three modes, Steno (the default), QWERTY (Toggleable) and a Momentary symbol layer
*
* Don't modify the steno layer directly, instead add chords using the keycodes and macros
* from sten.h to the layout you want to modify.
*
* Observe the comment above processQWERTY!
*
* http://docs.gboards.ca
*/
#include QMK_KEYBOARD_H
#include "sten.h"
#include "keymap_steno.h"
#define IGNORE_MOD_TAP_INTERRUPT
int getKeymapCount(void);
// Proper Layers
#define FUNCT (LSD | LK | LP | LH)
#define MEDIA (LSD | LK | LW | LR)
#define MOVE (ST1 | ST2)
/* Keyboard Layout
* ,---------------------------------. ,------------------------------.
* | FN | LSU | LFT | LP | LH | ST1 | | ST3 | RF | RP | RL | RT | RD |
* |-----+-----+-----+----+----|-----| |-----|----+----+----+----+----|
* | PWR | LSD | LK | LW | LR | ST2 | | ST4 | RR | RG | RB | RS | RZ |
* `---------------------------------' `------------------------------'
* ,---------------, .---------------.
* | NUM | LA | LO | | RE | RU | NUM |
* `---------------' `---------------'
*/
// YOU MUST ORDER THIS!
// P Will return from processing on the first match it finds. Therefore
// PJ Will run the requested action, remove the matched chord and continue
//
// First any chords that would conflict with PJs need to be checked, then PJs, lastly Ps.
// For all chords should be ordered by length in their section!
//
// http://docs.gboards.ca
bool processQwerty(void) {
// Place P's that would be trashed by PJ's here
P( RT | RS | RD | RZ | NUM, SEND_STRING(VERSION); SEND_STRING(__DATE__));
P( NUM | LA | LO | RE | RU, SEND(KC_MPLY));
P( ST1 | ST2 | ST3 | ST4, SEND(KC_BSPC));
// Thumb Chords
P( LA | LO | RE | RU, SEND(KC_CAPS));
P( LA | RU, SEND(KC_ESC));
PJ( LO | RE, SEND(KC_LCTL));
PJ( NUM | LA | RU, SEND(KC_LCTL); SEND(KC_LSFT));
PJ( NUM | LA | RE, SEND(KC_LCTL); SEND(KC_LSFT); SEND(KC_LALT));
// Mods
PJ( RT | RD | RS | RZ, SEND(KC_LGUI));
PJ( RT | RD, SEND(KC_LCTL));
PJ( RS | RZ, SEND(KC_LALT));
PJ( LA | NUM, SEND(KC_LCTL));
PJ( LA | LO, SEND(KC_LALT));
PJ( LO, SEND(KC_LSFT));
// Function Layer
P( FUNCT | RF | RR, SEND(KC_F5));
P( FUNCT | RP | RB, SEND(KC_F6));
P( FUNCT | RL | RG, SEND(KC_F7));
P( FUNCT | RT | RS, SEND(KC_F8));
P( FUNCT | RF, SEND(KC_F1));
P( FUNCT | RP, SEND(KC_F2));
P( FUNCT | RL, SEND(KC_F3));
P( FUNCT | RT, SEND(KC_F4));
P( FUNCT | RR, SEND(KC_F9));
P( FUNCT | RG, SEND(KC_F10));
P( FUNCT | RB, SEND(KC_F11));
P( FUNCT | RS, SEND(KC_F12));
// Movement Layer
P( MOVE | RF, SEND(KC_LEFT));
P( MOVE | RP, SEND(KC_DOWN));
P( MOVE | RL, SEND(KC_UP));
P( MOVE | RT, SEND(KC_RIGHT));
P( MOVE | ST3, SEND(KC_PGUP));
P( MOVE | ST4, SEND(KC_PGDN));
// Media Layer
P( MEDIA | RF, SEND(KC_MPRV));
P( MEDIA | RP, SEND(KC_MPLY));
P( MEDIA | RL, SEND(KC_MPLY));
P( MEDIA | RT, SEND(KC_MNXT));
P( MEDIA | RD, SEND(KC_VOLU));
P( MEDIA | RZ, SEND(KC_VOLD));
P( MEDIA | RS, SEND(KC_MUTE));
// Mouse Keys
P( LP | LH, clickMouse(KC_MS_BTN1));
P( LW | LR, clickMouse(KC_MS_BTN2));
// Number Row
P( NUM | LSU, SEND(KC_1));
P( NUM | LFT, SEND(KC_2));
P( NUM | LP, SEND(KC_3));
P( NUM | LH, SEND(KC_4));
P( NUM | ST1, SEND(KC_5));
P( NUM | ST3, SEND(KC_6));
P( NUM | RF, SEND(KC_7));
P( NUM | RP, SEND(KC_8));
P( NUM | RL, SEND(KC_9));
P( NUM | RT, SEND(KC_0));
P( NUM | LA, SEND(KC_5));
P( NUM | RT, SEND(KC_0));
// Specials
P( LA | NUM, SEND(KC_ESC));
P( RU | NUM, SEND(KC_TAB));
P( RE | RU, SEND(KC_BSPC));
P( RD | RZ, SEND(KC_ENT));
P( RE, SEND(KC_ENT));
P( RD, SEND(KC_BSPC));
P( NUM, SEND(KC_BSPC));
P( LA, SEND(KC_SPC));
P( RU, SEND(KC_SPC));
P( RZ, SEND(KC_ESC));
// Letters
P( LSU | LSD, SEND(KC_A));
P( LFT | LK, SEND(KC_S));
P( LP | LW, SEND(KC_D));
P( LH | LR, SEND(KC_F));
P( ST1 | ST2, SEND(KC_G));
P( ST3 | ST4, SEND(KC_H));
P( RF | RR, SEND(KC_J));
P( RT | RS, SEND(KC_SCLN))
P( RG | RL, SEND(KC_L));
P( RP | RB, SEND(KC_K));
P( LSU, SEND(KC_Q));
P( LSD, SEND(KC_Z));
P( LFT, SEND(KC_W));
P( LK, SEND(KC_X));
P( LP, SEND(KC_E));
P( LW, SEND(KC_C));
P( LH, SEND(KC_R));
P( LR, SEND(KC_V));
P( ST1, SEND(KC_T));
P( ST2, SEND(KC_B));
P( ST3, SEND(KC_Y));
P( ST4, SEND(KC_N));
P( RF, SEND(KC_U));
P( RR, SEND(KC_M));
P( RP, SEND(KC_I));
P( RB, SEND(KC_COMM));
P( RL, SEND(KC_O));
P( RG, SEND(KC_DOT));
P( RT, SEND(KC_P));
P( RS, SEND(KC_SLSH));
// Symbols and Numbers
P( PWR | RE | RU, SEND(KC_ENT));
P( PWR | LA | LO, SEND(KC_SPC));
P( PWR | LP | LW, SEND(KC_LSFT); SEND(KC_9)); // (
P( PWR | LH | LR, SEND(KC_LSFT); SEND(KC_0)); // )
P( PWR | ST1 | ST2, SEND(KC_GRV)); // `
P( PWR | RD | RZ, SEND(KC_ESC));
P( PWR | LSU | LSD, SEND(KC_LSFT); SEND(KC_3)); // #
P( PWR | LFT | LK, SEND(KC_LSFT); SEND(KC_4)); // $
P( PWR | LSU, SEND(KC_LSFT); SEND(KC_1)); // !
P( PWR | LSD, SEND(KC_LSFT); SEND(KC_5)); // %
P( PWR | LFT, SEND(KC_LSFT); SEND(KC_2)); // @
P( PWR | LK, SEND(KC_LSFT); SEND(KC_6)); // ^
P( PWR | LP, SEND(KC_LSFT); SEND(KC_LBRC)); // {
P( PWR | LW, SEND(KC_LBRC));
P( PWR | LH, SEND(KC_LSFT); SEND(KC_RBRC)); // }
P( PWR | LR, SEND(KC_RBRC));
P( PWR | ST1, SEND(KC_LSFT); SEND(KC_BSLS)); // |
P( PWR | ST2, SEND(KC_LSFT); SEND(KC_GRV)); // ~
P( PWR | ST3, SEND(KC_QUOT));
P( PWR | ST4, SEND(KC_LSFT); SEND(KC_QUOT)); // "
P( PWR | RF, SEND(KC_KP_PLUS));
P( PWR | RR, SEND(KC_LSFT); SEND(KC_7)); // &
P( PWR | RP, SEND(KC_MINS));
P( PWR | RB, SEND(KC_EQL));
P( PWR | RL, SEND(KC_SLSH));
P( PWR | RG, SEND(KC_COMM));
P( PWR | RT, SEND(KC_PAST));
P( PWR | RS, SEND(KC_DOT));
P( PWR | RD, SEND(KC_TAB));
P( PWR | LA, SEND(KC_SCLN));
P( PWR | LO, SEND(KC_SLSH));
P( PWR | RE, SEND(KC_SCLN));
P( PWR | RU, SEND(KC_SLSH));
// If we make here, send as a steno chord
// If plover is running we can hook that host side
return false;
}
#define STENO_LAYER 0
// "Layers"
// Steno layer should be first in your map.
// When PWR | FN | RR | RG | RB | RS is pressed, the layer is increased to the next map. You must return to STENO_LAYER at the end.
// If you have only a single layer, you must set SINGLELAYER = yes in your rules.mk, otherwise you may experince undefined behaviour
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Main layer, everything goes through here
[STENO_LAYER] = LAYOUT_georgi(
STN_FN, STN_S1, STN_TL, STN_PL, STN_HL, STN_ST1, STN_ST3, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR,
STN_PWR, STN_S2, STN_KL, STN_WL, STN_RL, STN_ST2, STN_ST4, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR,
STN_N1, STN_A, STN_O, STN_E, STN_U, STN_N1)
};
int getKeymapCount(void) {
return sizeof(keymaps)/sizeof(keymaps[0]);
}

View File

@@ -0,0 +1,6 @@
# Georgi QWERTY/Steno firmware
This is a blank template configured with 5K of free space for your onboard dictionary!
Read the docs over at [gBoards](http://docs.gboards.ca)
Ideally you should copy this directory and make your changes there. If you come up with a good layout submit a PR!

View File

@@ -0,0 +1,27 @@
#----------------------------------------------------------------------------
# make georgi:extrakey:dfu
# Make sure you have dfu-programmer installed!
#----------------------------------------------------------------------------
#Debug options
VERBOSE = yes
CONSOLE_ENABLE = yes
DEBUG_MATRIX_SCAN_RATE = no
DEBUG_MATRIX = no
KEYBOARD_SHARED_EP = yes
CUSTOM_MATRIX = yes
MOUSEKEY_ENABLE = no
SINGLE_LAYER = no
# A bunch of stuff that you shouldn't touch unless you
# know what you're doing.
#
# No touchy, capiche?
SRC += matrix.c i2c_master.c
ifeq ($(strip $(DEBUG_MATRIX)), yes)
OPT_DEFS += -DDEBUG_MATRIX
endif
ifeq ($(strip $(SINGLE_LAYER)), yes)
OPT_DEFS += -DSINGLE_LAYER
endif

View File

@@ -2,7 +2,7 @@
"keyboard_name": "kbd4x",
"url": "",
"maintainer": "qmk",
"width": 12,
"width": 14,
"height": 4,
"layouts": {
"LAYOUT_planck_mit": {

View File

@@ -2,8 +2,8 @@
"keyboard_name": "Iris",
"url": "https://keeb.io",
"maintainer": "Keebio",
"width": 15,
"height": 5.75,
"width": 14.5,
"height": 5,
"layouts": {
"LAYOUT": {
"layout": [

View File

@@ -54,7 +54,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SR_EXP_OE_N_PIN 15
/* SERCOM port to use for Shift Register SPI */
/* DATAOUT and SCLK must be configured to use hardware pins of this port */
#define SR_EXP_SERCOM SERCOM2
#define SR_EXP_SERCOM_NUM 2
/* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */
#define SR_EXP_DATAOUT_PORT PA
#define SR_EXP_DATAOUT_PIN 12
@@ -94,6 +94,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5
// Required BOOT key hold time (in ms) for restarting to bootloader -PS081419
#define BOOTKEY_HOLD_MS 2000
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
//#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */

View File

@@ -0,0 +1,81 @@
/*
Copyright 2019 Massdrop Inc.
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
//ADC configuration table column indices
#define ADC_PORT 0
#define ADC_PIN 1
#define ADC_MUX 2
#define ADC_INDEX 3
#define ADC_MUXPOS 4
#define ADC_REFSEL 5
#define ADC_SAMPLENUM 6
#define ADC_SAMPLEN 7
//ADC configuration table row indices
#define ADC_5V 0 //5V bus voltage
#define ADC_C1A5 1 //Connector 1 A5 CC voltage
#define ADC_C1B5 2 //Connector 1 B5 CC voltage
#define ADC_C2A5 3 //Connector 2 A5 CC voltage
#define ADC_C2B5 4 //Connector 2 B5 CC voltage
#define ADC_C1I 5 //Connector 1 current
#define ADC_C2I 6 //Connector 2 current
//ADC_PORT: PORT of the PIN on the MCU (Ex: 0 = PA, 1 = PB, ...)
// Set ADC_PORT to ADC_NA if it is not available for use
//ADC_PIN: PIN on the MCU (Ex: 0 = 00, 1 = 01, 12 = 12, ...)
//ADC_MUX: PMUX setting for the MCU PIN (Ex: 0 = A, 1 = B, 2 = C, ...)
//ADC_INDEX: ADC to use (Ex: 0 = ADC0, 1 = ADC1, ...)
//ADC_MUXPOS: MUXPOS setting to read on the ADC (Use macros from Atmel library adc.h ADC_INPUTCTRL_MUXPOS_AIN*_Val)
//ADC_REFSEL: Reference the ADC is to use (Use macros from Atmel library adc.h ADC_REFCTRL_REFSEL_*_Val)
//ADC_SAMPLENUM: Number of samples to average for output (Use macros from Atmel library adc.h ADC_AVGCTRL_SAMPLENUM_*_Val)
//ADC_SAMPLEN: Sampling time for each sample in units of CLK_ADC cycles depending on the ADC clock frequency
// ADC_PORT ADC_MUX
// | ADC_PIN | ADC_INDEX
// | | | | ADC_MUXPOS ADC_REFSEL ADC_SAMPLENUM ADC_SAMPLEN
#define ADC_CONFIG_5V 1, 0, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN12_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 45
#define ADC_CONFIG_C1A5 1, 2, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN14_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_16_Val, 63
#define ADC_CONFIG_C1B5 ADC_NA, 0, 0, 0, 0, 0, 0, 0
#define ADC_CONFIG_C2A5 1, 1, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN13_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_16_Val, 63
#define ADC_CONFIG_C2B5 ADC_NA, 0, 0, 0, 0, 0, 0, 0
#define ADC_CONFIG_C1I ADC_NA, 0, 0, 0, 0, 0, 0, 0
#define ADC_CONFIG_C2I ADC_NA, 0, 0, 0, 0, 0, 0, 0
//Conversion values dependant upon the circuitry
#define ADC_5V_VOLTS_PER_COUNT 0.001904297f
#define ADC_5V_VOLTS_OFFSET 0.0f
#define ADC_5V_NOMINAL 5.0f
#define ADC_5V_NOMINAL_COUNTS (ADC_5V_NOMINAL / ADC_5V_VOLTS_PER_COUNT)
//Conversion macros
#define ADC_5V_C2V(icounts) ((float)icounts * ADC_5V_VOLTS_PER_COUNT + ADC_5V_VOLTS_OFFSET) //Converts 5V Bus counts to volts
#define ADC_5V_V2C(v) (((float)v - ADC_5V_VOLTS_OFFSET) / ADC_5V_VOLTS_PER_COUNT) //Converts 5V Bus volts to counts
#define ADC_CC_5VCOR(v5counts, cc) ((float)v5counts == 0 ? 0 : ADC_5V_NOMINAL_COUNTS / (float)v5counts * (float)cc) //Corrects CC counts to nominal 5V value
#define ADC_USBC_EXTRA_NOMINAL 850 //Nominal ADC value for detection of connected device
#define ADC_USBC_EXTRA_NOMINAL_P1 1250 //Nominal ADC value for detection of connected device
//Note: Due to assembly error, USBC-1 J2 CC readings are wrong so we must check for special cases
#define USBC_IS_SINK(a5, b5) (USB_HOST_IS_2(g_usb_host_port) ? \
(a5 < ADC_USBC_EXTRA_NOMINAL_P1 || b5 < ADC_USBC_EXTRA_NOMINAL_P1) \
: \
(a5 < ADC_USBC_EXTRA_NOMINAL || b5 < ADC_USBC_EXTRA_NOMINAL) \
)
#define POWER_CHECK_INTERVAL 1 //How often to check power usage for adjustment and safety (ms)
#define V_5V_AVGS 50 //Number of 5V readings to average for algorithms wanting stable readings rather than instantaneous

View File

@@ -8,10 +8,14 @@
// This table can be almost-automatically derived from ISSI3733_LED_MAP that is
// defined in config_led.h
// scan in the following equations refers to the scan variable of ISSI3733_LED_MAP
// col = (uint8_t)(scan / 8)
// row = (uint8_t)(scan % 8)
//
// You can calculate the (0-244, 0-64) x/y values from the x/y values defined in
// ISSI3733_LED_MAP with the following formula:
// uint8_t rgb_x = ((ISSI3733_LED_MAP[i].x - MIN_X) / (MAX_X - MIN_X)) * 224;
// uint8_t rgb_y = ((ISSI3733_LED_MAP[i].y - MIN_Y) / (MAX_Y - MIN_Y)) * 64;
// uint8_t rgb_y = ((ISSI3733_LED_MAP[i].y - MIN_Y) / (MAX_Y - MIN_Y)) * 64; //TODO: 64 - this?
// Where the min/max vars are the minimum and maximum "bounds" of x/y values
// present in ISSI3733_LED_MAP
//

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -17,11 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
//Define number of ISSI3733 drivers being used (1...16)
//Define number of IS31FL3733 drivers being used (1...16)
#define ISSI3733_DRIVER_COUNT 2
#define DRIVER_LED_TOTAL ISSI3733_LED_COUNT
//Hardware address of each driver (Refer to ISSI3733 pdf "Table 1 Slave Address" and keyboard schematic)
//Hardware address of each driver (Refer to IS31FL3733 pdf "Table 1 Slave Address" and keyboard schematic)
#define ISSI3773_DRIVER_ADDRESSES { 0xA0, 0xBE }
//LED I2C bus speed
@@ -45,9 +45,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define ISSI3733_GCR_DEFAULT LED_GCR_MAX
//Automatic power rollback and recovery
#define V5_HIGH 2540 //5V high level (After low power detect, point at which LEDs are allowed to use more power )
#define V5_LOW 2480 //5V low level (LED power rolled back to stay above this limit)
#define V5_CAT 2200 //5V catastrophic level (Host USB port potential to shut down)
#define V5_HIGH 2494 //5V high level (After low power detect, point at which LEDs are allowed to use more power )
#define V5_LOW 2434 //5V low level (LED power rolled back to stay above this limit)
#define V5_CAT 2206 //5V catastrophic level (Host USB port potential to shut down)
//LED Mapping - More practically generated from a spreadsheet program
//id: ID of the LED (Sync with PCB callouts)
@@ -58,7 +58,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//swr: Matrix wiring SW Red row (1-12)
//swg: Matrix wiring SW Green row (1-12)
//swb: Matrix wiring SW Blue row (1-12)
//scan: Associated key scancode if any
//scan: Associated key matrix scancode (set 255 if none or 254 for LED to turn off in alternating mode)
//Note: Origin 0,0 may be located anywhere as the software will do the final layout
#define ISSI3733_LED_MAP { \
{ .id = 1, .x = 0, .y = 0, .adr = { .drv = 2, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 0 }, \
@@ -129,46 +129,45 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
{ .id = 66, .x = 10.5, .y = -3, .adr = { .drv = 1, .cs = 12, .swr = 8, .swg = 7, .swb = 9 }, .scan = 73 }, \
{ .id = 67, .x = 11.25, .y = -3, .adr = { .drv = 1, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 74 }, \
{ .id = 68, .x = -0.338, .y = -3.338, .adr = { .drv = 2, .cs = 11, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 69, .x = 0.39, .y = -3.443, .adr = { .drv = 2, .cs = 11, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 69, .x = 0.39, .y = -3.443, .adr = { .drv = 2, .cs = 11, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 70, .x = 1.263, .y = -3.443, .adr = { .drv = 2, .cs = 11, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 71, .x = 2.135, .y = -3.443, .adr = { .drv = 2, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 71, .x = 2.135, .y = -3.443, .adr = { .drv = 2, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 72, .x = 3.008, .y = -3.443, .adr = { .drv = 2, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 73, .x = 3.88, .y = -3.443, .adr = { .drv = 2, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 73, .x = 3.88, .y = -3.443, .adr = { .drv = 2, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 74, .x = 4.753, .y = -3.443, .adr = { .drv = 2, .cs = 13, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 75, .x = 5.625, .y = -3.443, .adr = { .drv = 2, .cs = 13, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 75, .x = 5.625, .y = -3.443, .adr = { .drv = 2, .cs = 13, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 76, .x = 6.497, .y = -3.443, .adr = { .drv = 1, .cs = 9, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 77, .x = 7.37, .y = -3.443, .adr = { .drv = 1, .cs = 9, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 77, .x = 7.37, .y = -3.443, .adr = { .drv = 1, .cs = 9, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 78, .x = 8.242, .y = -3.443, .adr = { .drv = 1, .cs = 9, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 79, .x = 9.115, .y = -3.443, .adr = { .drv = 1, .cs = 13, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 79, .x = 9.115, .y = -3.443, .adr = { .drv = 1, .cs = 13, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 80, .x = 9.987, .y = -3.443, .adr = { .drv = 1, .cs = 13, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 81, .x = 10.86, .y = -3.443, .adr = { .drv = 1, .cs = 13, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 81, .x = 10.86, .y = -3.443, .adr = { .drv = 1, .cs = 13, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 82, .x = 11.588, .y = -3.338, .adr = { .drv = 1, .cs = 13, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 83, .x = 11.693, .y = -2.623, .adr = { .drv = 1, .cs = 12, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 83, .x = 11.693, .y = -2.623, .adr = { .drv = 1, .cs = 12, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 84, .x = 11.693, .y = -1.873, .adr = { .drv = 1, .cs = 8, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 85, .x = 11.693, .y = -1.123, .adr = { .drv = 1, .cs = 8, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 86, .x = 11.693, .y = -0.373, .adr = { .drv = 1, .cs = 8, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 86, .x = 11.693, .y = -0.373, .adr = { .drv = 1, .cs = 8, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 87, .x = 11.588, .y = 0.338, .adr = { .drv = 1, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 88, .x = 9.908, .y = 0.443, .adr = { .drv = 1, .cs = 6, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 89, .x = 9.288, .y = 0.443, .adr = { .drv = 1, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 89, .x = 9.288, .y = 0.443, .adr = { .drv = 1, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 90, .x = 8.625, .y = 0.443, .adr = { .drv = 1, .cs = 4, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 91, .x = 7.875, .y = 0.443, .adr = { .drv = 1, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 91, .x = 7.875, .y = 0.443, .adr = { .drv = 1, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 92, .x = 7.125, .y = 0.443, .adr = { .drv = 1, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 93, .x = 6.375, .y = 0.443, .adr = { .drv = 1, .cs = 1, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 93, .x = 6.375, .y = 0.443, .adr = { .drv = 1, .cs = 1, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 94, .x = 5.625, .y = 0.443, .adr = { .drv = 1, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 95, .x = 4.875, .y = 0.443, .adr = { .drv = 2, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 95, .x = 4.875, .y = 0.443, .adr = { .drv = 2, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 96, .x = 4.125, .y = 0.443, .adr = { .drv = 2, .cs = 7, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 97, .x = 3.375, .y = 0.443, .adr = { .drv = 2, .cs = 6, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 97, .x = 3.375, .y = 0.443, .adr = { .drv = 2, .cs = 6, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 98, .x = 2.625, .y = 0.443, .adr = { .drv = 2, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 99, .x = 1.875, .y = 0.443, .adr = { .drv = 2, .cs = 4, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 99, .x = 1.875, .y = 0.443, .adr = { .drv = 2, .cs = 4, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 100, .x = 1.125, .y = 0.443, .adr = { .drv = 2, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 101, .x = -0.338, .y = 0.338, .adr = { .drv = 2, .cs = 1, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 102, .x = -0.443, .y = -0.373, .adr = { .drv = 2, .cs = 1, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 102, .x = -0.443, .y = -0.373, .adr = { .drv = 2, .cs = 1, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 103, .x = -0.443, .y = -1.123, .adr = { .drv = 2, .cs = 1, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 104, .x = -0.443, .y = -1.873, .adr = { .drv = 2, .cs = 1, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 105, .x = -0.443, .y = -2.623, .adr = { .drv = 2, .cs = 10, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 105, .x = -0.443, .y = -2.623, .adr = { .drv = 2, .cs = 10, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
};
#define USB_LED_INDICATOR_ENABLE //Comment out to disable indicator functionality
#ifdef USB_LED_INDICATOR_ENABLE //Scan codes refer to actual key matrix codes, not KC_* (255 to disable)
#define USB_LED_NUM_LOCK_SCANCODE 255

View File

@@ -0,0 +1,42 @@
/*
Copyright 2019 Massdrop Inc.
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
/* Data structure to define Shift Register output expander hardware */
/* This structure gets shifted into registers LSB first */
typedef union {
struct {
uint16_t RSVD4:1; /*!< bit: 0 */
uint16_t RSVD3:1; /*!< bit: 1 */
uint16_t RSVD2:1; /*!< bit: 2 */
uint16_t RSVD1:1; /*!< bit: 3 */
uint16_t SDB_N:1; /*!< bit: 4 SHUTDOWN IS31FL3733 CHIPS WHEN 0, RUN WHEN 1 */
uint16_t IRST:1; /*!< bit: 5 RESET IS31FL3733 I2C WHEN 1, RUN WHEN 0 */
uint16_t SRC_2:1; /*!< bit: 6 ADVERTISE A SOURCE TO USBC-2 CC */
uint16_t SRC_1:1; /*!< bit: 7 ADVERTISE A SOURCE TO USBC-1 CC */
uint16_t E_VBUS_2:1; /*!< bit: 8 ENABLE 5V OUT TO USBC-2 WHEN 1 */
uint16_t E_VBUS_1:1; /*!< bit: 9 ENABLE 5V OUT TO USBC-1 WHEN 1 */
uint16_t E_DN1_N:1; /*!< bit: 10 ENABLE DN1 1:2 MUX WHEN 0 */
uint16_t S_DN1:1; /*!< bit: 11 SELECT DN1 PATH 0:USBC-1, 1:USBC-2 */
uint16_t E_UP_N:1; /*!< bit: 12 ENABLE SUP 1:2 MUX WHEN 0 */
uint16_t S_UP:1; /*!< bit: 13 SELECT UP PATH 0:USBC-1, 1:USBC-2 */
uint16_t HUB_RESET_N:1; /*!< bit: 14 RESET USB HUB WHEN 0, RUN WHEN 1 */
uint16_t HUB_CONNECT:1; /*!< bit: 15 SIGNAL VBUS CONNECT TO USB HUB WHEN 1 */
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} sr_exp_t;

View File

@@ -0,0 +1,28 @@
/*
Copyright 2019 Massdrop Inc.
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
//Macros to Enable, Disable, and Update USB 5V bus connections
#define USBC_CFG_5V1_VAR sr_exp_data.bit.E_VBUS_1 //Variable storing USBC-1 5V Bus state
#define USBC_CFG_5V1_ENA 1 //Value to enable USBC-1 5V Bus
#define USBC_CFG_5V1_DIS 0 //Value to disable USBC-1 5V Bus
#define USBC_CFG_5V1_UPDATE SR_EXP_WriteData() //Command to run to update value
#define USBC_CFG_5V2_VAR sr_exp_data.bit.E_VBUS_2 //Variable storing USBC-2 5V Bus state
#define USBC_CFG_5V2_ENA 1 //Value to enable USBC-1 5V Bus
#define USBC_CFG_5V2_DIS 0 //Value to disable USBC-1 5V Bus
#define USBC_CFG_5V2_UPDATE SR_EXP_WriteData() //Command to run to update value

View File

@@ -1,8 +1,7 @@
#include QMK_KEYBOARD_H
enum alt_keycodes {
U_T_AUTO = SAFE_RANGE, //USB Extra Port Toggle Auto Detect / Always Active
U_T_AGCR, //USB Toggle Automatic GCR control
U_T_AGCR = SAFE_RANGE, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
@@ -24,7 +23,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[1] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_MUTE, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, U_T_AUTO,U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, _______, U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
_______, RGB_RMOD,RGB_VAD, RGB_MOD, RGB_HUD, RGB_SAD, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, \
_______, RGB_TOG, _______, _______, _______, MD_BOOT, TG_NKRO, DBG_TOG, _______, _______, _______, _______, KC_PGUP, KC_VOLD, \
_______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END \
@@ -56,11 +55,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
switch (keycode) {
case U_T_AUTO:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");

View File

@@ -1,8 +1,7 @@
#include QMK_KEYBOARD_H
enum alt_keycodes {
U_T_AUTO = SAFE_RANGE, //USB Extra Port Toggle Auto Detect / Always Active
U_T_AGCR, //USB Toggle Automatic GCR control
U_T_AGCR = SAFE_RANGE, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
@@ -24,7 +23,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[1] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_MUTE, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, U_T_AUTO,U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, _______, U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
_______, RGB_RMOD,RGB_VAD, RGB_MOD, RGB_HUD, RGB_SAD, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, \
_______, RGB_TOG, _______, _______, _______, MD_BOOT, TG_NKRO, DBG_TOG, _______, _______, _______, _______, KC_PGUP, KC_VOLD, \
_______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END \
@@ -56,11 +55,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
switch (keycode) {
case U_T_AUTO:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
@@ -90,7 +84,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}
@@ -125,3 +119,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true; //Process all other keycodes normally
}
}
led_instruction_t led_instructions[] = {
{ .end = 1 }
};

View File

@@ -1,24 +1,28 @@
#include QMK_KEYBOARD_H
enum alt_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase //Working
L_BRD, //LED Brightness Decrease //Working
L_PTN, //LED Pattern Select Next //Working
L_PTP, //LED Pattern Select Previous //Working
L_PSI, //LED Pattern Speed Increase //Working
L_PSD, //LED Pattern Speed Decrease //Working
L_T_MD, //LED Toggle Mode //Working
L_T_ONF, //LED Toggle On / Off //Broken
L_ON, //LED On //Broken
L_OFF, //LED Off //Broken
L_T_BR, //LED Toggle Breath Effect //Working
L_T_PTD, //LED Toggle Scrolling Pattern Direction //Working
U_T_AGCR, //USB Toggle Automatic GCR control //Working
DBG_TOG, //DEBUG Toggle On / Off //
DBG_MTRX, //DEBUG Toggle Matrix Prints //
DBG_KBD, //DEBUG Toggle Keyboard Prints //
DBG_MOU, //DEBUG Toggle Mouse Prints //
MD_BOOT //Restart into bootloader after hold timeout //Working
L_BRI = SAFE_RANGE, //LED Brightness Increase
L_BRD, //LED Brightness Decrease
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next
L_PTP, //LED Pattern Select Previous
L_PSI, //LED Pattern Speed Increase
L_PSD, //LED Pattern Speed Decrease
L_T_MD, //LED Toggle Mode
L_T_ONF, //LED Toggle On / Off
L_ON, //LED On
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction and effect
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
DBG_FAC, //DEBUG Factory light testing (All on white)
MD_BOOT //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
@@ -35,10 +39,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[1] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_MUTE, \
L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, _______, U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, \
_______, L_T_MD, L_T_ONF, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, KC_PGUP, KC_VOLD, \
_______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END \
L_T_BR, L_PSD, L_BRI, L_PSI, L_EDG_I, _______, _______, _______, U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
L_T_PTD, L_PTP, L_BRD, L_PTN, L_EDG_D, _______, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, \
_______, L_T_MD, L_T_ONF, _______, L_EDG_M, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, KC_PGUP, KC_VOLD, \
_______, _______, _______, DBG_FAC, _______, _______, KC_HOME, KC_PGDN, KC_END \
),
/*
[X] = LAYOUT(
@@ -59,12 +63,13 @@ void matrix_init_user(void) {
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
static uint8_t scroll_effect = 0;
switch (keycode) {
case L_BRI:
@@ -81,6 +86,26 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_EDG_M:
if (record->event.pressed) {
led_edge_mode++;
if (led_edge_mode > LED_EDGE_MODE_MAX) {
led_edge_mode = LED_EDGE_MODE_ALL;
}
}
return false;
case L_EDG_I:
if (record->event.pressed) {
led_edge_brightness += 0.1;
if (led_edge_brightness > 1) { led_edge_brightness = 1; }
}
return false;
case L_EDG_D:
if (record->event.pressed) {
led_edge_brightness -= 0.1;
if (led_edge_brightness < 0) { led_edge_brightness = 0; }
}
return false;
case L_PTN:
if (record->event.pressed) {
if (led_animation_id == led_setups_count - 1) led_animation_id = 0;
@@ -112,20 +137,17 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
case L_T_ONF:
if (record->event.pressed) {
led_enabled = !led_enabled;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(!I2C3733_Control_Get());
}
return false;
case L_ON:
if (record->event.pressed) {
led_enabled = 1;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(1);
}
return false;
case L_OFF:
if (record->event.pressed) {
led_enabled = 0;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(0);
}
return false;
case L_T_BR:
@@ -140,7 +162,33 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
case L_T_PTD:
if (record->event.pressed) {
led_animation_direction = !led_animation_direction;
scroll_effect++;
if (scroll_effect == 1) { //Patterns with scroll move horizontal (Right to left)
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 0;
} else if (scroll_effect == 2) { //Patterns with scroll move vertical (Top to bottom)
led_animation_direction = 1;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 3) { //Patterns with scroll move vertical (Bottom to top)
led_animation_direction = 0;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 4) { //Patterns with scroll explode from center
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 1;
} else if (scroll_effect == 5) { //Patterns with scroll implode on center
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 1;
} else { //Patterns with scroll move horizontal (Left to right)
scroll_effect = 0;
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 0;
}
}
return false;
case U_T_AGCR:
@@ -148,6 +196,17 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_FAC:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
led_lighting_mode = LED_MODE_NORMAL;
led_edge_brightness = 1;
led_edge_mode = LED_EDGE_MODE_ALL;
led_animation_breathing = 0;
led_animation_id = 7; //led_programs.c led_setups leds_white index
gcr_desired = LED_GCR_MAX;
I2C3733_Control_Set(1);
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
@@ -172,7 +231,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}

View File

@@ -1,8 +1,7 @@
#include QMK_KEYBOARD_H
enum alt_keycodes {
U_T_AUTO = SAFE_RANGE, //USB Extra Port Toggle Auto Detect / Always Active
U_T_AGCR, //USB Toggle Automatic GCR control
U_T_AGCR = SAFE_RANGE, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
@@ -24,7 +23,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[1] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_MUTE, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, U_T_AUTO,U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, _______, U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
_______, RGB_RMOD,RGB_VAD, RGB_MOD, RGB_HUD, RGB_SAD, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, \
_______, RGB_TOG, _______, _______, _______, MD_BOOT, TG_NKRO, DBG_TOG, _______, _______, _______, _______, KC_PGUP, KC_VOLD, \
_______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END \
@@ -56,11 +55,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
switch (keycode) {
case U_T_AUTO:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
@@ -90,7 +84,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}
@@ -125,3 +119,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true; //Process all other keycodes normally
}
}
led_instruction_t led_instructions[] = {
{ .end = 1 }
};

View File

@@ -1,24 +1,28 @@
#include QMK_KEYBOARD_H
enum alt_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase //Working
L_BRD, //LED Brightness Decrease //Working
L_PTN, //LED Pattern Select Next //Working
L_PTP, //LED Pattern Select Previous //Working
L_PSI, //LED Pattern Speed Increase //Working
L_PSD, //LED Pattern Speed Decrease //Working
L_T_MD, //LED Toggle Mode //Working
L_T_ONF, //LED Toggle On / Off //Broken
L_ON, //LED On //Broken
L_OFF, //LED Off //Broken
L_T_BR, //LED Toggle Breath Effect //Working
L_T_PTD, //LED Toggle Scrolling Pattern Direction //Working
U_T_AGCR, //USB Toggle Automatic GCR control //Working
DBG_TOG, //DEBUG Toggle On / Off //
DBG_MTRX, //DEBUG Toggle Matrix Prints //
DBG_KBD, //DEBUG Toggle Keyboard Prints //
DBG_MOU, //DEBUG Toggle Mouse Prints //
MD_BOOT //Restart into bootloader after hold timeout //Working
L_BRI = SAFE_RANGE, //LED Brightness Increase
L_BRD, //LED Brightness Decrease
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next
L_PTP, //LED Pattern Select Previous
L_PSI, //LED Pattern Speed Increase
L_PSD, //LED Pattern Speed Decrease
L_T_MD, //LED Toggle Mode
L_T_ONF, //LED Toggle On / Off
L_ON, //LED On
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction and effect
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
DBG_FAC, //DEBUG Factory light testing (All on white)
MD_BOOT //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
@@ -35,10 +39,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[1] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_MUTE, \
L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, _______, U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, \
_______, L_T_MD, L_T_ONF, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, KC_PGUP, KC_VOLD, \
_______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END \
L_T_BR, L_PSD, L_BRI, L_PSI, L_EDG_I, _______, _______, _______, U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
L_T_PTD, L_PTP, L_BRD, L_PTN, L_EDG_D, _______, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, \
_______, L_T_MD, L_T_ONF, _______, L_EDG_M, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, KC_PGUP, KC_VOLD, \
_______, _______, _______, DBG_FAC, _______, _______, KC_HOME, KC_PGDN, KC_END \
),
/*
[X] = LAYOUT(
@@ -59,12 +63,13 @@ void matrix_init_user(void) {
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
static uint8_t scroll_effect = 0;
switch (keycode) {
case L_BRI:
@@ -81,6 +86,26 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_EDG_M:
if (record->event.pressed) {
led_edge_mode++;
if (led_edge_mode > LED_EDGE_MODE_MAX) {
led_edge_mode = LED_EDGE_MODE_ALL;
}
}
return false;
case L_EDG_I:
if (record->event.pressed) {
led_edge_brightness += 0.1;
if (led_edge_brightness > 1) { led_edge_brightness = 1; }
}
return false;
case L_EDG_D:
if (record->event.pressed) {
led_edge_brightness -= 0.1;
if (led_edge_brightness < 0) { led_edge_brightness = 0; }
}
return false;
case L_PTN:
if (record->event.pressed) {
if (led_animation_id == led_setups_count - 1) led_animation_id = 0;
@@ -112,20 +137,17 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
case L_T_ONF:
if (record->event.pressed) {
led_enabled = !led_enabled;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(!I2C3733_Control_Get());
}
return false;
case L_ON:
if (record->event.pressed) {
led_enabled = 1;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(1);
}
return false;
case L_OFF:
if (record->event.pressed) {
led_enabled = 0;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(0);
}
return false;
case L_T_BR:
@@ -140,7 +162,33 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
case L_T_PTD:
if (record->event.pressed) {
led_animation_direction = !led_animation_direction;
scroll_effect++;
if (scroll_effect == 1) { //Patterns with scroll move horizontal (Right to left)
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 0;
} else if (scroll_effect == 2) { //Patterns with scroll move vertical (Top to bottom)
led_animation_direction = 1;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 3) { //Patterns with scroll move vertical (Bottom to top)
led_animation_direction = 0;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 4) { //Patterns with scroll explode from center
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 1;
} else if (scroll_effect == 5) { //Patterns with scroll implode on center
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 1;
} else { //Patterns with scroll move horizontal (Left to right)
scroll_effect = 0;
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 0;
}
}
return false;
case U_T_AGCR:
@@ -148,6 +196,17 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_FAC:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
led_lighting_mode = LED_MODE_NORMAL;
led_edge_brightness = 1;
led_edge_mode = LED_EDGE_MODE_ALL;
led_animation_breathing = 0;
led_animation_id = 7; //led_programs.c led_setups leds_white index
gcr_desired = LED_GCR_MAX;
I2C3733_Control_Set(1);
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
@@ -172,7 +231,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}

View File

@@ -14,7 +14,6 @@ enum alt_keycodes {
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction
U_T_AUTO, //USB Extra Port Toggle Auto Detect / Always Active
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
@@ -38,7 +37,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[1] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_MUTE, \
_______, _______, _______, KC_UP, _______, _______, _______, U_T_AUTO,U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
_______, _______, _______, KC_UP, _______, _______, _______, _______, U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_END, \
_______, _______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, KC_VOLU, _______, \
_______, _______, _______, KC_MPLY, MO(2), _______, KC_MRWD, KC_VOLD, KC_MFFD \
@@ -146,11 +145,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
led_animation_direction = !led_animation_direction;
}
return false;
case U_T_AUTO:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -22,6 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "clks.h"
#include <string.h>
#define MCU_PORTS_USED 2 //PA, PB
matrix_row_t mlatest[MATRIX_ROWS];
matrix_row_t mlast[MATRIX_ROWS];
matrix_row_t mdebounced[MATRIX_ROWS];
@@ -30,7 +32,7 @@ uint8_t row_ports[] = { MATRIX_ROW_PORTS };
uint8_t row_pins[] = { MATRIX_ROW_PINS };
uint8_t col_ports[] = { MATRIX_COL_PORTS };
uint8_t col_pins[] = { MATRIX_COL_PINS };
uint32_t row_masks[2]; //NOTE: If more than PA PB used in the future, adjust code to accomodate
uint32_t row_masks[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
__attribute__ ((weak))
void matrix_init_kb(void) {
@@ -56,9 +58,9 @@ void matrix_init(void)
memset(mlast, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(mdebounced, 0, MATRIX_ROWS * sizeof(matrix_row_t));
row_masks[PA] = 0;
row_masks[PB] = 0;
memset(row_masks, 0, sizeof(row_masks));
//Inputs
uint8_t row;
for (row = 0; row < MATRIX_ROWS; row++)
{
@@ -69,6 +71,7 @@ void matrix_init(void)
row_masks[row_ports[row]] |= 1 << row_pins[row]; //Add pin to proper row mask
}
//Outputs
uint8_t col;
for (col = 0; col < MATRIX_COLS; col++)
{
@@ -80,27 +83,29 @@ void matrix_init(void)
}
uint64_t mdebouncing = 0;
bool debouncing = false;
uint8_t matrix_scan(void)
{
uint8_t mchanged;
uint64_t timer;
uint8_t row;
uint8_t col;
uint32_t scans[2]; //PA PB
if (timer_read64() < mdebouncing) return 1; //mdebouncing == 0 when no debouncing active
uint32_t scans[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
memset(mlatest, 0, MATRIX_ROWS * sizeof(matrix_row_t)); //Zero the result buffer
for (col = 0; col < MATRIX_COLS; col++)
{
PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; //Set col output
//Set output
PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; //Set col output
wait_us(1); //Delay for output
wait_us(1); //Delay for output
//Read input (add unique ports as needed, PA, PB, PC, etc)
scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; //Read PA row pins data
scans[PB] = PORT->Group[PB].IN.reg & row_masks[PB]; //Read PA row pins data
scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; //Read PA row pins data
scans[PB] = PORT->Group[PB].IN.reg & row_masks[PB]; //Read PB row pins data
PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Clear col output
//Clear output
PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Clear col output
for (row = 0; row < MATRIX_ROWS; row++)
{
@@ -110,25 +115,26 @@ uint8_t matrix_scan(void)
}
}
mchanged = 0; //Default to no matrix change since last
timer = timer_read64();
for (row = 0; row < MATRIX_ROWS; row++)
{
if (mlast[row] != mlatest[row])
mchanged = 1;
if (mlast[row] != mlatest[row]) {
debouncing = true;
mdebouncing = timer + DEBOUNCE;
}
mlast[row] = mlatest[row];
}
if (!mchanged)
if (debouncing && timer >= mdebouncing)
{
for (row = 0; row < MATRIX_ROWS; row++)
for (row = 0; row < MATRIX_ROWS; row++) {
mdebounced[row] = mlatest[row];
}
mdebouncing = 0;
}
else
{
//Begin or extend debounce on change
mdebouncing = timer_read64() + DEBOUNCE;
debouncing = false;
}
matrix_scan_quantum();

View File

@@ -1,6 +1,8 @@
# project specific files
SRC = matrix.c
SRC += config_led.c
SRC += spi.c
SRC += usb.c
#For platform and packs
ARM_ATSAM = SAMD51J18A

View File

@@ -0,0 +1,57 @@
/*
Copyright 2019 Massdrop Inc.
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 "arm_atsam_protocol.h"
void SR_EXP_Init_kb(void) {
/* Initialize shift register */
SR_EXP_OE_N_DIS;
SR_EXP_RCLK_HI;
SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; //Data Order - LSB is transferred first
SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; //Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; //Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3; //Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; //Data Output PAD[0], Serial Clock PAD[1]
SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; //Operating Mode - Master operation
SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; //Enable - Peripheral is enabled or being enabled
while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { DBGC(DC_SPI_EXP_SYNC_ENABLING); }
/* Set default shift register values */
sr_exp_data.reg = 0; //Clear data register
sr_exp_data.bit.HUB_CONNECT = 0; //USB Hub disconnected
sr_exp_data.bit.HUB_RESET_N = 0; //USB Hub in reset state
sr_exp_data.bit.SRC_1 = 1; //Set CON1 CC A5/B5 as Rd 5.1k
sr_exp_data.bit.SRC_2 = 1; //Set CON2 CC A5/B5 as Rd 5.1k
sr_exp_data.bit.S_UP = 0; //Default USB data to CON1
sr_exp_data.bit.E_UP_N = 1; //Disable HOST
sr_exp_data.bit.S_DN1 = 1; //Default EXTRA port to CON2
sr_exp_data.bit.E_DN1_N = 1; //Disable EXTRA
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
sr_exp_data.bit.IRST = 1; //LED drivers I2C in reset
sr_exp_data.bit.SDB_N = 0; //LED drivers in shutdown
/* Write shift register data */
SR_EXP_WriteData();
/* Enable shift register output */
SR_EXP_OE_N_ENA;
}

View File

@@ -0,0 +1,83 @@
/*
Copyright 2019 Massdrop Inc.
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 "arm_atsam_protocol.h"
//Note: rp_best_index not used
void usb_set_host_kb(uint8_t con, uint8_t rp_best_index) {
if (con == 1) {
sr_exp_data.bit.S_UP = 0; //HOST to USBC-1
sr_exp_data.bit.S_DN1 = 1; //EXTRA to USBC-2
g_usb_host_port = USB_HOST_PORT_1; //Save host port
sr_exp_data.bit.E_VBUS_1 = 1; //Enable CON1 5V
SR_EXP_WriteData(); //Update port configuration
} else if (con == 2) {
sr_exp_data.bit.S_DN1 = 0; //HOST to USBC-2
sr_exp_data.bit.S_UP = 1; //EXTRA to USBC-1
g_usb_host_port = USB_HOST_PORT_2; //Save host port
sr_exp_data.bit.E_VBUS_2 = 1; //Enable CON2 5V
SR_EXP_WriteData(); //Update port configuration
}
}
void usb_set_extra_kb(uint8_t con) {
if (con == 1) {
sr_exp_data.bit.SRC_1 = 0; //Set CON1 CC A5/B5 as Rp 56k
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
SR_EXP_WriteData(); //Update port configuration
} else if (con == 2) {
sr_exp_data.bit.SRC_2 = 0; //Set CON2 CC A5/B5 as Rp 56k
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
SR_EXP_WriteData(); //Update port configuration
}
}
void usb_init_host_detection_kb(void) {
//Disable 5V
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
//Configure default paths
sr_exp_data.bit.S_UP = 0; //HOST to USBC-1
sr_exp_data.bit.S_DN1 = 1; //EXTRA to USBC-2
//Configure CC lines
sr_exp_data.bit.SRC_1 = 1; //Set CON1 CC A5/B5 as Rd 5.1k
sr_exp_data.bit.SRC_2 = 1; //Set CON2 CC A5/B5 as Rd 5.1k
//Enable ports
sr_exp_data.bit.E_UP_N = 0; //Enable HOST for use
sr_exp_data.bit.E_DN1_N = 0; //Enable EXTRA for use
SR_EXP_WriteData(); //Update port configuration
}
//Return 1 if configuration successful
//Return 0 otherwise
uint8_t usb_attach_port_configure_kb(uint8_t g_usb_host_port, uint16_t usbc_cc_a5_v, uint16_t usbc_cc_b5_v) {
if (USB_HOST_IS_1(g_usb_host_port)) { //If host is port 1
//Set up port 2
usb_set_extra_kb(2);
return 1;
} else if (USB_HOST_IS_2(g_usb_host_port)) { //If host is on port 2
//Set up port 1
usb_set_extra_kb(1);
return 1;
}
return 0;
}

View File

@@ -54,7 +54,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SR_EXP_OE_N_PIN 15
/* SERCOM port to use for Shift Register SPI */
/* DATAOUT and SCLK must be configured to use hardware pins of this port */
#define SR_EXP_SERCOM SERCOM2
#define SR_EXP_SERCOM_NUM 2
/* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */
#define SR_EXP_DATAOUT_PORT PA
#define SR_EXP_DATAOUT_PIN 12
@@ -94,6 +94,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5
// Required BOOT key hold time (in ms) for restarting to bootloader -PS081419
#define BOOTKEY_HOLD_MS 2000
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
//#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */

View File

@@ -0,0 +1,75 @@
/*
Copyright 2019 Massdrop Inc.
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
//ADC configuration table column indices
#define ADC_PORT 0
#define ADC_PIN 1
#define ADC_MUX 2
#define ADC_INDEX 3
#define ADC_MUXPOS 4
#define ADC_REFSEL 5
#define ADC_SAMPLENUM 6
#define ADC_SAMPLEN 7
//ADC configuration table row indices
#define ADC_5V 0 //5V bus voltage
#define ADC_C1A5 1 //Connector 1 A5 CC voltage
#define ADC_C1B5 2 //Connector 1 B5 CC voltage
#define ADC_C2A5 3 //Connector 2 A5 CC voltage
#define ADC_C2B5 4 //Connector 2 B5 CC voltage
#define ADC_C1I 5 //Connector 1 current
#define ADC_C2I 6 //Connector 2 current
//ADC_PORT: PORT of the PIN on the MCU (Ex: 0 = PA, 1 = PB, ...)
// Set ADC_PORT to ADC_NA if it is not available for use
//ADC_PIN: PIN on the MCU (Ex: 0 = 00, 1 = 01, 12 = 12, ...)
//ADC_MUX: PMUX setting for the MCU PIN (Ex: 0 = A, 1 = B, 2 = C, ...)
//ADC_INDEX: ADC to use (Ex: 0 = ADC0, 1 = ADC1, ...)
//ADC_MUXPOS: MUXPOS setting to read on the ADC (Use macros from Atmel library adc.h ADC_INPUTCTRL_MUXPOS_AIN*_Val)
//ADC_REFSEL: Reference the ADC is to use (Use macros from Atmel library adc.h ADC_REFCTRL_REFSEL_*_Val)
//ADC_SAMPLENUM: Number of samples to average for output (Use macros from Atmel library adc.h ADC_AVGCTRL_SAMPLENUM_*_Val)
//ADC_SAMPLEN: Sampling time for each sample in units of CLK_ADC cycles depending on the ADC clock frequency
// ADC_PORT ADC_MUX
// | ADC_PIN | ADC_INDEX
// | | | | ADC_MUXPOS ADC_REFSEL ADC_SAMPLENUM ADC_SAMPLEN
#define ADC_CONFIG_5V 1, 0, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN12_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 45
#define ADC_CONFIG_C1A5 1, 2, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN14_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_16_Val, 63
#define ADC_CONFIG_C1B5 ADC_NA, 0, 0, 0, 0, 0, 0, 0
#define ADC_CONFIG_C2A5 1, 1, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN13_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_16_Val, 63
#define ADC_CONFIG_C2B5 ADC_NA, 0, 0, 0, 0, 0, 0, 0
#define ADC_CONFIG_C1I ADC_NA, 0, 0, 0, 0, 0, 0, 0
#define ADC_CONFIG_C2I ADC_NA, 0, 0, 0, 0, 0, 0, 0
//Conversion values dependant upon the circuitry
#define ADC_5V_VOLTS_PER_COUNT 0.001904297f
#define ADC_5V_VOLTS_OFFSET 0.0f
#define ADC_5V_NOMINAL 5.0f
#define ADC_5V_NOMINAL_COUNTS (ADC_5V_NOMINAL / ADC_5V_VOLTS_PER_COUNT)
//Conversion macros
#define ADC_5V_C2V(icounts) ((float)icounts * ADC_5V_VOLTS_PER_COUNT + ADC_5V_VOLTS_OFFSET) //Converts 5V Bus counts to volts
#define ADC_5V_V2C(v) (((float)v - ADC_5V_VOLTS_OFFSET) / ADC_5V_VOLTS_PER_COUNT) //Converts 5V Bus volts to counts
#define ADC_CC_5VCOR(v5counts, cc) ((float)v5counts == 0 ? 0 : ADC_5V_NOMINAL_COUNTS / (float)v5counts * (float)cc) //Corrects CC counts to nominal 5V value
#define ADC_USBC_EXTRA_NOMINAL 850 //Nominal ADC value for detection of connected device
#define USBC_IS_SINK(a5, b5) (a5 < ADC_USBC_EXTRA_NOMINAL || b5 < ADC_USBC_EXTRA_NOMINAL)
#define POWER_CHECK_INTERVAL 1 //How often to check power usage for adjustment and safety (ms)
#define V_5V_AVGS 50 //Number of 5V readings to average for algorithms wanting stable readings rather than instantaneous

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -17,11 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
//Define number of ISSI3733 drivers being used (1...16)
//Define number of IS31FL3733 drivers being used (1...16)
#define ISSI3733_DRIVER_COUNT 2
#define DRIVER_LED_TOTAL ISSI3733_LED_COUNT
//Hardware address of each driver (Refer to ISSI3733 pdf "Table 1 Slave Address" and keyboard schematic)
//Hardware address of each driver (Refer to IS31FL3733 pdf "Table 1 Slave Address" and keyboard schematic)
#define ISSI3773_DRIVER_ADDRESSES { 0xA0, 0xBE }
//LED I2C bus speed
@@ -45,9 +45,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define ISSI3733_GCR_DEFAULT LED_GCR_MAX
//Automatic power rollback and recovery
#define V5_HIGH 2540 //5V high level (After low power detect, point at which LEDs are allowed to use more power )
#define V5_LOW 2480 //5V low level (LED power rolled back to stay above this limit)
#define V5_CAT 2200 //5V catastrophic level (Host USB port potential to shut down)
#define V5_HIGH 2494 //5V high level (After low power detect, point at which LEDs are allowed to use more power )
#define V5_LOW 2434 //5V low level (LED power rolled back to stay above this limit)
#define V5_CAT 2206 //5V catastrophic level (Host USB port potential to shut down)
//LED Mapping - More practically generated from a spreadsheet program
//id: ID of the LED (Sync with PCB callouts)
@@ -58,7 +58,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//swr: Matrix wiring SW Red row (1-12)
//swg: Matrix wiring SW Green row (1-12)
//swb: Matrix wiring SW Blue row (1-12)
//scan: Associated key scancode if any
//scan: Associated key matrix scancode (set 255 if none or 254 for LED to turn off in alternating mode)
//Note: Origin 0,0 may be located anywhere as the software will do the final layout
#define ISSI3733_LED_MAP { \
{ .id = 1, .x = 0, .y = 0, .adr = { .drv = 2, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 0 }, \
@@ -149,37 +149,37 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
{ .id = 86, .x = 12.375, .y = -4.125, .adr = { .drv = 1, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 85 }, \
{ .id = 87, .x = 13.125, .y = -4.125, .adr = { .drv = 1, .cs = 11, .swr = 5, .swg = 4, .swb = 6 }, .scan = 86 }, \
{ .id = 88, .x = 13.433, .y = -4.43, .adr = { .drv = 1, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 89, .x = 12.285, .y = -4.535, .adr = { .drv = 1, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 89, .x = 12.285, .y = -4.535, .adr = { .drv = 1, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 90, .x = 11.14, .y = -4.535, .adr = { .drv = 1, .cs = 13, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 91, .x = 9.995, .y = -4.535, .adr = { .drv = 1, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 91, .x = 9.995, .y = -4.535, .adr = { .drv = 1, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 92, .x = 8.85, .y = -4.535, .adr = { .drv = 1, .cs = 15, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 93, .x = 7.705, .y = -4.535, .adr = { .drv = 1, .cs = 16, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 93, .x = 7.705, .y = -4.535, .adr = { .drv = 1, .cs = 16, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 94, .x = 6.56, .y = -4.535, .adr = { .drv = 2, .cs = 9, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 95, .x = 5.415, .y = -4.535, .adr = { .drv = 2, .cs = 10, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 95, .x = 5.415, .y = -4.535, .adr = { .drv = 2, .cs = 10, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 96, .x = 4.27, .y = -4.535, .adr = { .drv = 2, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 97, .x = 3.125, .y = -4.535, .adr = { .drv = 2, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 97, .x = 3.125, .y = -4.535, .adr = { .drv = 2, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 98, .x = 1.98, .y = -4.535, .adr = { .drv = 2, .cs = 13, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 99, .x = 0.835, .y = -4.535, .adr = { .drv = 2, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 99, .x = 0.835, .y = -4.535, .adr = { .drv = 2, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 100, .x = -0.307, .y = -4.43, .adr = { .drv = 2, .cs = 15, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 101, .x = -0.41, .y = -3.245, .adr = { .drv = 2, .cs = 15, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 101, .x = -0.41, .y = -3.245, .adr = { .drv = 2, .cs = 15, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 102, .x = -0.41, .y = -2.06, .adr = { .drv = 2, .cs = 15, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 103, .x = -0.41, .y = -0.875, .adr = { .drv = 2, .cs = 15, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 103, .x = -0.41, .y = -0.875, .adr = { .drv = 2, .cs = 15, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 104, .x = -0.308, .y = 0.31, .adr = { .drv = 2, .cs = 1, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 105, .x = 0.835, .y = 0.415, .adr = { .drv = 2, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 105, .x = 0.835, .y = 0.415, .adr = { .drv = 2, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 106, .x = 1.98, .y = 0.415, .adr = { .drv = 2, .cs = 4, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 107, .x = 3.125, .y = 0.415, .adr = { .drv = 2, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 107, .x = 3.125, .y = 0.415, .adr = { .drv = 2, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 108, .x = 4.27, .y = 0.415, .adr = { .drv = 2, .cs = 7, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 109, .x = 5.415, .y = 0.415, .adr = { .drv = 2, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 109, .x = 5.415, .y = 0.415, .adr = { .drv = 2, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 110, .x = 6.56, .y = 0.415, .adr = { .drv = 1, .cs = 1, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 111, .x = 7.705, .y = 0.415, .adr = { .drv = 1, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 111, .x = 7.705, .y = 0.415, .adr = { .drv = 1, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 112, .x = 8.85, .y = 0.415, .adr = { .drv = 1, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 113, .x = 9.995, .y = 0.415, .adr = { .drv = 1, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 113, .x = 9.995, .y = 0.415, .adr = { .drv = 1, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 114, .x = 11.14, .y = 0.415, .adr = { .drv = 1, .cs = 6, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 115, .x = 12.285, .y = 0.415, .adr = { .drv = 1, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 115, .x = 12.285, .y = 0.415, .adr = { .drv = 1, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 116, .x = 13.432, .y = 0.31, .adr = { .drv = 1, .cs = 10, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 117, .x = 13.535, .y = -0.875, .adr = { .drv = 1, .cs = 10, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 117, .x = 13.535, .y = -0.875, .adr = { .drv = 1, .cs = 10, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 118, .x = 13.535, .y = -2.06, .adr = { .drv = 1, .cs = 10, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 119, .x = 13.535, .y = -3.245, .adr = { .drv = 1, .cs = 10, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 119, .x = 13.535, .y = -3.245, .adr = { .drv = 1, .cs = 10, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
};
#define USB_LED_INDICATOR_ENABLE //Comment out to disable indicator functionality

View File

@@ -0,0 +1,42 @@
/*
Copyright 2019 Massdrop Inc.
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
/* Data structure to define Shift Register output expander hardware */
/* This structure gets shifted into registers LSB first */
typedef union {
struct {
uint16_t RSVD4:1; /*!< bit: 0 */
uint16_t RSVD3:1; /*!< bit: 1 */
uint16_t RSVD2:1; /*!< bit: 2 */
uint16_t RSVD1:1; /*!< bit: 3 */
uint16_t SDB_N:1; /*!< bit: 4 SHUTDOWN IS31FL3733 CHIPS WHEN 0, RUN WHEN 1 */
uint16_t IRST:1; /*!< bit: 5 RESET IS31FL3733 I2C WHEN 1, RUN WHEN 0 */
uint16_t SRC_2:1; /*!< bit: 6 ADVERTISE A SOURCE TO USBC-2 CC */
uint16_t SRC_1:1; /*!< bit: 7 ADVERTISE A SOURCE TO USBC-1 CC */
uint16_t E_VBUS_2:1; /*!< bit: 8 ENABLE 5V OUT TO USBC-2 WHEN 1 */
uint16_t E_VBUS_1:1; /*!< bit: 9 ENABLE 5V OUT TO USBC-1 WHEN 1 */
uint16_t E_DN1_N:1; /*!< bit: 10 ENABLE DN1 1:2 MUX WHEN 0 */
uint16_t S_DN1:1; /*!< bit: 11 SELECT DN1 PATH 0:USBC-1, 1:USBC-2 */
uint16_t E_UP_N:1; /*!< bit: 12 ENABLE SUP 1:2 MUX WHEN 0 */
uint16_t S_UP:1; /*!< bit: 13 SELECT UP PATH 0:USBC-1, 1:USBC-2 */
uint16_t HUB_RESET_N:1; /*!< bit: 14 RESET USB HUB WHEN 0, RUN WHEN 1 */
uint16_t HUB_CONNECT:1; /*!< bit: 15 SIGNAL VBUS CONNECT TO USB HUB WHEN 1 */
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} sr_exp_t;

View File

@@ -0,0 +1,28 @@
/*
Copyright 2019 Massdrop Inc.
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
//Macros to Enable, Disable, and Update USB 5V bus connections
#define USBC_CFG_5V1_VAR sr_exp_data.bit.E_VBUS_1 //Variable storing USBC-1 5V Bus state
#define USBC_CFG_5V1_ENA 1 //Value to enable USBC-1 5V Bus
#define USBC_CFG_5V1_DIS 0 //Value to disable USBC-1 5V Bus
#define USBC_CFG_5V1_UPDATE SR_EXP_WriteData() //Command to run to update value
#define USBC_CFG_5V2_VAR sr_exp_data.bit.E_VBUS_2 //Variable storing USBC-2 5V Bus state
#define USBC_CFG_5V2_ENA 1 //Value to enable USBC-1 5V Bus
#define USBC_CFG_5V2_DIS 0 //Value to disable USBC-1 5V Bus
#define USBC_CFG_5V2_UPDATE SR_EXP_WriteData() //Command to run to update value

View File

@@ -1,8 +1,7 @@
#include QMK_KEYBOARD_H
enum ctrl_keycodes {
U_T_AUTO = SAFE_RANGE, //USB Extra Port Toggle Auto Detect / Always Active
U_T_AGCR, //USB Toggle Automatic GCR control
U_T_AGCR = SAFE_RANGE, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
@@ -26,7 +25,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[1] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, U_T_AUTO,U_T_AGCR,_______, _______, _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
_______, RGB_RMOD,RGB_VAD, RGB_MOD, RGB_HUD, RGB_SAD, _______, _______, _______, _______, _______, _______, _______, \
_______, RGB_TOG, _______, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
@@ -37,7 +36,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
),
*/
@@ -59,11 +58,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
switch (keycode) {
case U_T_AUTO:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
@@ -93,7 +87,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}
@@ -128,3 +122,15 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true; //Process all other keycodes normally
}
}
led_instruction_t led_instructions[] = {
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 10, .id1 = 9, .r = 255, .g = 0, .b = 0 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_PATTERN, .id0 = 4, .id1 = 0, .pattern_id = 8 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 8, .id1 = 0, .r = 0, .g = 255, .b = 0 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_PATTERN, .id = 16, .id1 = 0, .pattern_id = 9 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 32, .id1 = 0, .r = 0, .g = 0, .b = 255 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_ROTATE_PATTERN, .id0 = 64, .id1 = 0},
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_MATCH_LAYER | LED_FLAG_USE_ROTATE_PATTERN, .id0 = 262144, .id1 = 0, .layer = 0 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_MATCH_LAYER | LED_FLAG_USE_ROTATE_PATTERN, .id = 16777216, .id1 = 0, .layer = 1 },
{ .end = 1 }
};

View File

@@ -1,24 +1,28 @@
#include QMK_KEYBOARD_H
enum ctrl_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase //Working
L_BRD, //LED Brightness Decrease //Working
L_PTN, //LED Pattern Select Next //Working
L_PTP, //LED Pattern Select Previous //Working
L_PSI, //LED Pattern Speed Increase //Working
L_PSD, //LED Pattern Speed Decrease //Working
L_T_MD, //LED Toggle Mode //Working
L_T_ONF, //LED Toggle On / Off //Broken
L_ON, //LED On //Broken
L_OFF, //LED Off //Broken
L_T_BR, //LED Toggle Breath Effect //Working
L_T_PTD, //LED Toggle Scrolling Pattern Direction //Working
U_T_AGCR, //USB Toggle Automatic GCR control //Working
DBG_TOG, //DEBUG Toggle On / Off //
DBG_MTRX, //DEBUG Toggle Matrix Prints //
DBG_KBD, //DEBUG Toggle Keyboard Prints //
DBG_MOU, //DEBUG Toggle Mouse Prints //
MD_BOOT //Restart into bootloader after hold timeout //Working
L_BRI = SAFE_RANGE, //LED Brightness Increase
L_BRD, //LED Brightness Decrease
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next
L_PTP, //LED Pattern Select Previous
L_PSI, //LED Pattern Speed Increase
L_PSD, //LED Pattern Speed Decrease
L_T_MD, //LED Toggle Mode
L_T_ONF, //LED Toggle On / Off
L_ON, //LED On
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction and effect
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
DBG_FAC, //DEBUG Factory light testing (All on white)
MD_BOOT //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
@@ -30,26 +34,26 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS, \
KC_GRV, 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_HOME, KC_PGUP, \
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_END, KC_PGDN, \
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_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_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT \
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_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_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT \
),
[1] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, \
L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, L_T_MD, L_T_ONF, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
L_T_BR, L_PSD, L_BRI, L_PSI, L_EDG_I, _______, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
L_T_PTD, L_PTP, L_BRD, L_PTN, L_EDG_D, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, L_T_MD, L_T_ONF, _______, L_EDG_M, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, DBG_FAC, _______, _______, _______, _______, _______, _______, _______ \
),
/*
[X] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
),
*/
};
@@ -62,12 +66,13 @@ void matrix_init_user(void) {
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
static uint8_t scroll_effect = 0;
switch (keycode) {
case L_BRI:
@@ -84,6 +89,26 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_EDG_M:
if (record->event.pressed) {
led_edge_mode++;
if (led_edge_mode > LED_EDGE_MODE_MAX) {
led_edge_mode = LED_EDGE_MODE_ALL;
}
}
return false;
case L_EDG_I:
if (record->event.pressed) {
led_edge_brightness += 0.1;
if (led_edge_brightness > 1) { led_edge_brightness = 1; }
}
return false;
case L_EDG_D:
if (record->event.pressed) {
led_edge_brightness -= 0.1;
if (led_edge_brightness < 0) { led_edge_brightness = 0; }
}
return false;
case L_PTN:
if (record->event.pressed) {
if (led_animation_id == led_setups_count - 1) led_animation_id = 0;
@@ -115,20 +140,17 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
case L_T_ONF:
if (record->event.pressed) {
led_enabled = !led_enabled;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(!I2C3733_Control_Get());
}
return false;
case L_ON:
if (record->event.pressed) {
led_enabled = 1;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(1);
}
return false;
case L_OFF:
if (record->event.pressed) {
led_enabled = 0;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(0);
}
return false;
case L_T_BR:
@@ -143,7 +165,33 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
case L_T_PTD:
if (record->event.pressed) {
led_animation_direction = !led_animation_direction;
scroll_effect++;
if (scroll_effect == 1) { //Patterns with scroll move horizontal (Right to left)
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 0;
} else if (scroll_effect == 2) { //Patterns with scroll move vertical (Top to bottom)
led_animation_direction = 1;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 3) { //Patterns with scroll move vertical (Bottom to top)
led_animation_direction = 0;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 4) { //Patterns with scroll explode from center
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 1;
} else if (scroll_effect == 5) { //Patterns with scroll implode on center
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 1;
} else { //Patterns with scroll move horizontal (Left to right)
scroll_effect = 0;
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 0;
}
}
return false;
case U_T_AGCR:
@@ -151,6 +199,17 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_FAC:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
led_lighting_mode = LED_MODE_NORMAL;
led_edge_brightness = 1;
led_edge_mode = LED_EDGE_MODE_ALL;
led_animation_breathing = 0;
led_animation_id = 7; //led_programs.c led_setups leds_white index
gcr_desired = LED_GCR_MAX;
I2C3733_Control_Set(1);
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
@@ -175,7 +234,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}

View File

@@ -1,8 +1,7 @@
#include QMK_KEYBOARD_H
enum ctrl_keycodes {
U_T_AUTO = SAFE_RANGE, //USB Extra Port Toggle Auto Detect / Always Active
U_T_AGCR, //USB Toggle Automatic GCR control
U_T_AGCR = SAFE_RANGE, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
@@ -26,7 +25,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[1] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, U_T_AUTO,U_T_AGCR,_______, _______, _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
_______, RGB_RMOD,RGB_VAD, RGB_MOD, RGB_HUD, RGB_SAD, _______, _______, _______, _______, _______, _______, _______, \
_______, RGB_TOG, _______, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
@@ -37,7 +36,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
),
*/
@@ -59,11 +58,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
switch (keycode) {
case U_T_AUTO:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
@@ -93,7 +87,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}
@@ -128,3 +122,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true; //Process all other keycodes normally
}
}
led_instruction_t led_instructions[] = {
{ .end = 1 }
};

View File

@@ -1,24 +1,28 @@
#include QMK_KEYBOARD_H
enum ctrl_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase //Working
L_BRD, //LED Brightness Decrease //Working
L_PTN, //LED Pattern Select Next //Working
L_PTP, //LED Pattern Select Previous //Working
L_PSI, //LED Pattern Speed Increase //Working
L_PSD, //LED Pattern Speed Decrease //Working
L_T_MD, //LED Toggle Mode //Working
L_T_ONF, //LED Toggle On / Off //Broken
L_ON, //LED On //Broken
L_OFF, //LED Off //Broken
L_T_BR, //LED Toggle Breath Effect //Working
L_T_PTD, //LED Toggle Scrolling Pattern Direction //Working
U_T_AGCR, //USB Toggle Automatic GCR control //Working
DBG_TOG, //DEBUG Toggle On / Off //
DBG_MTRX, //DEBUG Toggle Matrix Prints //
DBG_KBD, //DEBUG Toggle Keyboard Prints //
DBG_MOU, //DEBUG Toggle Mouse Prints //
MD_BOOT //Restart into bootloader after hold timeout //Working
L_BRI = SAFE_RANGE, //LED Brightness Increase
L_BRD, //LED Brightness Decrease
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next
L_PTP, //LED Pattern Select Previous
L_PSI, //LED Pattern Speed Increase
L_PSD, //LED Pattern Speed Decrease
L_T_MD, //LED Toggle Mode
L_T_ONF, //LED Toggle On / Off
L_ON, //LED On
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction and effect
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
DBG_FAC, //DEBUG Factory light testing (All on white)
MD_BOOT //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
@@ -30,26 +34,26 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS, \
KC_GRV, 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_HOME, KC_PGUP, \
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_END, KC_PGDN, \
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_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_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(1), KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT \
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_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_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(1), KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT \
),
[1] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, \
L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, L_T_MD, L_T_ONF, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
L_T_BR, L_PSD, L_BRI, L_PSI, L_EDG_I, _______, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
L_T_PTD, L_PTP, L_BRD, L_PTN, L_EDG_D, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, L_T_MD, L_T_ONF, _______, L_EDG_M, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, DBG_FAC, _______, _______, _______, _______, _______, _______, _______ \
),
/*
[X] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
),
*/
};
@@ -62,12 +66,13 @@ void matrix_init_user(void) {
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
static uint8_t scroll_effect = 0;
switch (keycode) {
case L_BRI:
@@ -84,6 +89,26 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_EDG_M:
if (record->event.pressed) {
led_edge_mode++;
if (led_edge_mode > LED_EDGE_MODE_MAX) {
led_edge_mode = LED_EDGE_MODE_ALL;
}
}
return false;
case L_EDG_I:
if (record->event.pressed) {
led_edge_brightness += 0.1;
if (led_edge_brightness > 1) { led_edge_brightness = 1; }
}
return false;
case L_EDG_D:
if (record->event.pressed) {
led_edge_brightness -= 0.1;
if (led_edge_brightness < 0) { led_edge_brightness = 0; }
}
return false;
case L_PTN:
if (record->event.pressed) {
if (led_animation_id == led_setups_count - 1) led_animation_id = 0;
@@ -115,20 +140,17 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
case L_T_ONF:
if (record->event.pressed) {
led_enabled = !led_enabled;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(!I2C3733_Control_Get());
}
return false;
case L_ON:
if (record->event.pressed) {
led_enabled = 1;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(1);
}
return false;
case L_OFF:
if (record->event.pressed) {
led_enabled = 0;
I2C3733_Control_Set(led_enabled);
I2C3733_Control_Set(0);
}
return false;
case L_T_BR:
@@ -143,7 +165,33 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
case L_T_PTD:
if (record->event.pressed) {
led_animation_direction = !led_animation_direction;
scroll_effect++;
if (scroll_effect == 1) { //Patterns with scroll move horizontal (Right to left)
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 0;
} else if (scroll_effect == 2) { //Patterns with scroll move vertical (Top to bottom)
led_animation_direction = 1;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 3) { //Patterns with scroll move vertical (Bottom to top)
led_animation_direction = 0;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 4) { //Patterns with scroll explode from center
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 1;
} else if (scroll_effect == 5) { //Patterns with scroll implode on center
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 1;
} else { //Patterns with scroll move horizontal (Left to right)
scroll_effect = 0;
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 0;
}
}
return false;
case U_T_AGCR:
@@ -151,6 +199,17 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_FAC:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
led_lighting_mode = LED_MODE_NORMAL;
led_edge_brightness = 1;
led_edge_mode = LED_EDGE_MODE_ALL;
led_animation_breathing = 0;
led_animation_id = 7; //led_programs.c led_setups leds_white index
gcr_desired = LED_GCR_MAX;
I2C3733_Control_Set(1);
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
@@ -175,7 +234,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}

View File

@@ -29,7 +29,6 @@ enum ctrl_keycodes {
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction
U_T_AUTO, //USB Extra Port Toggle Auto Detect / Always Active
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
@@ -67,7 +66,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[1] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, \
L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, U_T_AUTO,U_T_AGCR,_______, MO(2), _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, _______, U_T_AGCR,_______, MO(2), _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, L_T_MD, L_T_ONF, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
@@ -777,11 +776,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
led_animation_direction = !led_animation_direction;
}
return false;
case U_T_AUTO:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -22,6 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "clks.h"
#include <string.h>
#define MCU_PORTS_USED 2 //PA, PB
matrix_row_t mlatest[MATRIX_ROWS];
matrix_row_t mlast[MATRIX_ROWS];
matrix_row_t mdebounced[MATRIX_ROWS];
@@ -30,7 +32,7 @@ uint8_t row_ports[] = { MATRIX_ROW_PORTS };
uint8_t row_pins[] = { MATRIX_ROW_PINS };
uint8_t col_ports[] = { MATRIX_COL_PORTS };
uint8_t col_pins[] = { MATRIX_COL_PINS };
uint32_t row_masks[2]; //NOTE: If more than PA PB used in the future, adjust code to accomodate
uint32_t row_masks[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
__attribute__ ((weak))
void matrix_init_kb(void) {
@@ -56,9 +58,9 @@ void matrix_init(void)
memset(mlast, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(mdebounced, 0, MATRIX_ROWS * sizeof(matrix_row_t));
row_masks[PA] = 0;
row_masks[PB] = 0;
memset(row_masks, 0, sizeof(row_masks));
//Inputs
uint8_t row;
for (row = 0; row < MATRIX_ROWS; row++)
{
@@ -69,6 +71,7 @@ void matrix_init(void)
row_masks[row_ports[row]] |= 1 << row_pins[row]; //Add pin to proper row mask
}
//Outputs
uint8_t col;
for (col = 0; col < MATRIX_COLS; col++)
{
@@ -80,27 +83,29 @@ void matrix_init(void)
}
uint64_t mdebouncing = 0;
bool debouncing = false;
uint8_t matrix_scan(void)
{
uint8_t mchanged;
uint64_t timer;
uint8_t row;
uint8_t col;
uint32_t scans[2]; //PA PB
if (timer_read64() < mdebouncing) return 1; //mdebouncing == 0 when no debouncing active
uint32_t scans[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
memset(mlatest, 0, MATRIX_ROWS * sizeof(matrix_row_t)); //Zero the result buffer
for (col = 0; col < MATRIX_COLS; col++)
{
PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; //Set col output
//Set output
PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; //Set col output
wait_us(1); //Delay for output
wait_us(1); //Delay for output
//Read input (add unique ports as needed, PA, PB, PC, etc)
scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; //Read PA row pins data
scans[PB] = PORT->Group[PB].IN.reg & row_masks[PB]; //Read PA row pins data
scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; //Read PA row pins data
scans[PB] = PORT->Group[PB].IN.reg & row_masks[PB]; //Read PB row pins data
PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Clear col output
//Clear output
PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Clear col output
for (row = 0; row < MATRIX_ROWS; row++)
{
@@ -110,25 +115,26 @@ uint8_t matrix_scan(void)
}
}
mchanged = 0; //Default to no matrix change since last
timer = timer_read64();
for (row = 0; row < MATRIX_ROWS; row++)
{
if (mlast[row] != mlatest[row])
mchanged = 1;
if (mlast[row] != mlatest[row]) {
debouncing = true;
mdebouncing = timer + DEBOUNCE;
}
mlast[row] = mlatest[row];
}
if (!mchanged)
if (debouncing && timer >= mdebouncing)
{
for (row = 0; row < MATRIX_ROWS; row++)
for (row = 0; row < MATRIX_ROWS; row++) {
mdebounced[row] = mlatest[row];
}
mdebouncing = 0;
}
else
{
//Begin or extend debounce on change
mdebouncing = timer_read64() + DEBOUNCE;
debouncing = false;
}
matrix_scan_quantum();

View File

@@ -1,6 +1,8 @@
# project specific files
SRC = matrix.c
SRC += config_led.c
SRC += spi.c
SRC += usb.c
#For platform and packs
ARM_ATSAM = SAMD51J18A

View File

@@ -0,0 +1,57 @@
/*
Copyright 2019 Massdrop Inc.
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 "arm_atsam_protocol.h"
void SR_EXP_Init_kb(void) {
/* Initialize shift register */
SR_EXP_OE_N_DIS;
SR_EXP_RCLK_HI;
SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; //Data Order - LSB is transferred first
SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; //Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; //Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3; //Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; //Data Output PAD[0], Serial Clock PAD[1]
SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; //Operating Mode - Master operation
SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; //Enable - Peripheral is enabled or being enabled
while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { DBGC(DC_SPI_EXP_SYNC_ENABLING); }
/* Set default shift register values */
sr_exp_data.reg = 0; //Clear data register
sr_exp_data.bit.HUB_CONNECT = 0; //USB Hub disconnected
sr_exp_data.bit.HUB_RESET_N = 0; //USB Hub in reset state
sr_exp_data.bit.SRC_1 = 1; //Set CON1 CC A5/B5 as Rd 5.1k
sr_exp_data.bit.SRC_2 = 1; //Set CON2 CC A5/B5 as Rd 5.1k
sr_exp_data.bit.S_UP = 0; //Default USB data to CON1
sr_exp_data.bit.E_UP_N = 1; //Disable HOST
sr_exp_data.bit.S_DN1 = 1; //Default EXTRA port to CON2
sr_exp_data.bit.E_DN1_N = 1; //Disable EXTRA
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
sr_exp_data.bit.IRST = 1; //LED drivers I2C in reset
sr_exp_data.bit.SDB_N = 0; //LED drivers in shutdown
/* Write shift register data */
SR_EXP_WriteData();
/* Enable shift register output */
SR_EXP_OE_N_ENA;
}

View File

@@ -0,0 +1,83 @@
/*
Copyright 2019 Massdrop Inc.
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 "arm_atsam_protocol.h"
//Note: rp_best_index not used
void usb_set_host_kb(uint8_t con, uint8_t rp_best_index) {
if (con == 1) {
sr_exp_data.bit.S_UP = 0; //HOST to USBC-1
sr_exp_data.bit.S_DN1 = 1; //EXTRA to USBC-2
g_usb_host_port = USB_HOST_PORT_1; //Save host port
sr_exp_data.bit.E_VBUS_1 = 1; //Enable CON1 5V
SR_EXP_WriteData(); //Update port configuration
} else if (con == 2) {
sr_exp_data.bit.S_DN1 = 0; //HOST to USBC-2
sr_exp_data.bit.S_UP = 1; //EXTRA to USBC-1
g_usb_host_port = USB_HOST_PORT_2; //Save host port
sr_exp_data.bit.E_VBUS_2 = 1; //Enable CON2 5V
SR_EXP_WriteData(); //Update port configuration
}
}
void usb_set_extra_kb(uint8_t con) {
if (con == 1) {
sr_exp_data.bit.SRC_1 = 0; //Set CON1 CC A5/B5 as Rp 56k
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
SR_EXP_WriteData(); //Update port configuration
} else if (con == 2) {
sr_exp_data.bit.SRC_2 = 0; //Set CON2 CC A5/B5 as Rp 56k
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
SR_EXP_WriteData(); //Update port configuration
}
}
void usb_init_host_detection_kb(void) {
//Disable 5V
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
//Configure default paths
sr_exp_data.bit.S_UP = 0; //HOST to USBC-1
sr_exp_data.bit.S_DN1 = 1; //EXTRA to USBC-2
//Configure CC lines
sr_exp_data.bit.SRC_1 = 1; //Set CON1 CC A5/B5 as Rd 5.1k
sr_exp_data.bit.SRC_2 = 1; //Set CON2 CC A5/B5 as Rd 5.1k
//Enable ports
sr_exp_data.bit.E_UP_N = 0; //Enable HOST for use
sr_exp_data.bit.E_DN1_N = 0; //Enable EXTRA for use
SR_EXP_WriteData(); //Update port configuration
}
//Return 1 if configuration successful
//Return 0 otherwise
uint8_t usb_attach_port_configure_kb(uint8_t g_usb_host_port, uint16_t usbc_cc_a5_v, uint16_t usbc_cc_b5_v) {
if (USB_HOST_IS_1(g_usb_host_port)) { //If host is port 1
//Set up port 2
usb_set_extra_kb(2);
return 1;
} else if (USB_HOST_IS_2(g_usb_host_port)) { //If host is on port 2
//Set up port 1
usb_set_extra_kb(1);
return 1;
}
return 0;
}

View File

@@ -0,0 +1,132 @@
/*
Copyright 2015 Jun Wako <wakojun@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 0x04D8
#define PRODUCT_ID 0xEE66
#define DEVICE_VER 0x0100
#define MANUFACTURER "Massdrop Inc."
#define PRODUCT "Massdrop x Zslane Mercury Rocketeer Keyboard"
#define SERIAL_NUM "Unavailable"
/* key matrix size */
#define MATRIX_ROWS 5
#define MATRIX_COLS 14
/* MCU Port name definitions */
#define PA 0
#define PB 1
/* Port and Pin definition of key row hardware configuration */
#define MATRIX_ROW_PORTS PB, PB, PB, PB, PA
#define MATRIX_ROW_PINS 6, 7, 8, 9, 4
/* Port and Pin definition of key column hardware configuration */
#define MATRIX_COL_PORTS PB, PA, PA, PA, PA, PB, PB, PA, PA, PA, PB, PB, PB, PB
#define MATRIX_COL_PINS 3, 0, 1, 2, 3, 30, 31, 5, 6, 7, 10, 11, 12, 13
/* This Shift Register expands available hardware output lines to control additional peripherals */
/* It uses four lines from the MCU to provide 16 output lines */
/* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */
#define SR_EXP_RCLK_PORT PB
#define SR_EXP_RCLK_PIN 14
/* Shift Register Output Enable configuration (MCU to ShiftRegister.OE_N) */
#define SR_EXP_OE_N_PORT PB
#define SR_EXP_OE_N_PIN 15
/* SERCOM port to use for Shift Register SPI */
/* DATAOUT and SCLK must be configured to use hardware pins of this port */
#define SR_EXP_SERCOM_NUM 2
/* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */
#define SR_EXP_DATAOUT_PORT PA
#define SR_EXP_DATAOUT_PIN 12
#define SR_EXP_DATAOUT_MUX 2
/* Shift Register SPI Serial Clock configuration (MCU.SERCOMx.PAD[1] to ShiftRegister.SRCLK) */
#define SR_EXP_SCLK_PORT PA
#define SR_EXP_SCLK_PIN 13
#define SR_EXP_SCLK_MUX 2
/* Debug LED (Small LED Located near MCU) */
/* PCB D94 */
#define DEBUG_LED_ENABLE 1
#define DEBUG_LED_PORT PA
#define DEBUG_LED_PIN 27
/* Additional debugging ports */
/* PCB M25 */
#define DEBUG_PORT1_ENABLE 1
#define DEBUG_PORT1_PORT PA
#define DEBUG_PORT1_PIN 20
/* PCB M26 */
#define DEBUG_PORT2_ENABLE 1
#define DEBUG_PORT2_PORT PA
#define DEBUG_PORT2_PIN 21
/* PCB M23 */
#define DEBUG_PORT3_ENABLE 1
#define DEBUG_PORT3_PORT PB
#define DEBUG_PORT3_PIN 17
/* Debug Boot Tracing - During boot sequence, ground this pin to halt and display debug code using Debug LED */
/* This is useful in determining which hardware device may have malfunctioned or is improperly configured */
/* Feature is automatically disabled after successful boot */
/* PCB M27 */
#define DEBUG_BOOT_TRACING_ENABLE 1
#define DEBUG_BOOT_TRACING_PORT PB
#define DEBUG_BOOT_TRACING_PIN 23
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5
// Required BOOT key hold time (in ms) for restarting to bootloader -PS081419
#define BOOTKEY_HOLD_MS 2000
/* 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 boot in NKRO mode */
//#define FORCE_NKRO
/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/
/* disable debug print */
//#define NO_DEBUG
/* disable print */
//#define NO_PRINT
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION
#define RGB_MATRIX_KEYPRESSES
#define RGB_MATRIX_LED_PROCESS_LIMIT 15
#define RGB_MATRIX_LED_FLUSH_LIMIT 10
#define RGB_MATRIX_EXTRA_TOG
#include "config_led.h"

View File

@@ -0,0 +1,118 @@
/*
Copyright 2019 Massdrop Inc.
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
//ADC configuration table column indices
#define ADC_PORT 0
#define ADC_PIN 1
#define ADC_MUX 2
#define ADC_INDEX 3
#define ADC_MUXPOS 4
#define ADC_REFSEL 5
#define ADC_SAMPLENUM 6
#define ADC_SAMPLEN 7
//ADC configuration table row indices
#define ADC_5V 0 //5V bus voltage
#define ADC_C1A5 1 //Connector 1 A5 CC voltage
#define ADC_C1B5 2 //Connector 1 B5 CC voltage
#define ADC_C2A5 3 //Connector 2 A5 CC voltage
#define ADC_C2B5 4 //Connector 2 B5 CC voltage
#define ADC_C1I 5 //Connector 1 current
#define ADC_C2I 6 //Connector 2 current
//ADC_PORT: PORT of the PIN on the MCU (Ex: 0 = PA, 1 = PB, ...)
// Set ADC_PORT to ADC_NA if it is not available for use
//ADC_PIN: PIN on the MCU (Ex: 0 = 00, 1 = 01, 12 = 12, ...)
//ADC_MUX: PMUX setting for the MCU PIN (Ex: 0 = A, 1 = B, 2 = C, ...)
//ADC_INDEX: ADC to use (Ex: 0 = ADC0, 1 = ADC1, ...)
//ADC_MUXPOS: MUXPOS setting to read on the ADC (Use macros from Atmel library adc.h ADC_INPUTCTRL_MUXPOS_AIN*_Val)
//ADC_REFSEL: Reference the ADC is to use (Use macros from Atmel library adc.h ADC_REFCTRL_REFSEL_*_Val)
//ADC_SAMPLENUM: Number of samples to average for output (Use macros from Atmel library adc.h ADC_AVGCTRL_SAMPLENUM_*_Val)
//ADC_SAMPLEN: Sampling time for each sample in units of CLK_ADC cycles depending on the ADC clock frequency
// ADC_PORT ADC_MUX
// | ADC_PIN | ADC_INDEX
// | | | | ADC_MUXPOS ADC_REFSEL ADC_SAMPLENUM ADC_SAMPLEN
#define ADC_CONFIG_5V 1, 0, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN12_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 45
#define ADC_CONFIG_C1A5 1, 2, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN14_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 63
#define ADC_CONFIG_C1B5 1, 4, 1, 1, ADC_INPUTCTRL_MUXPOS_AIN6_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 63
#define ADC_CONFIG_C2A5 1, 1, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN13_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 63
#define ADC_CONFIG_C2B5 1, 5, 1, 1, ADC_INPUTCTRL_MUXPOS_AIN7_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 63
#define ADC_CONFIG_C1I 0, 10, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN10_Val, ADC_REFCTRL_REFSEL_INTVCC1_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 45
#define ADC_CONFIG_C2I 0, 11, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN11_Val, ADC_REFCTRL_REFSEL_INTVCC1_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 45
//Conversion values dependant upon the circuitry
#define ADC_I_MILLIAMPS_PER_COUNT -0.000980472f
#define ADC_I_MILLIAMPS_OFFSET 1.979711769f
#define ADC_5V_VOLTS_PER_COUNT 0.001904297f
#define ADC_5V_VOLTS_OFFSET 0.0f
#define ADC_5V_NOMINAL 5.0f
#define ADC_5V_NOMINAL_COUNTS (ADC_5V_NOMINAL / ADC_5V_VOLTS_PER_COUNT)
//Conversion macros
#define ADC_CI_C2I(macounts) ((float)macounts * ADC_I_MILLIAMPS_PER_COUNT + ADC_I_MILLIAMPS_OFFSET) //Converts connector current counts to milliamps
#define ADC_CI_I2C(ma) (uint16_t)((((float)ma - ADC_I_MILLIAMPS_OFFSET) / ADC_I_MILLIAMPS_PER_COUNT)) //Converts milliamps to connector current counts
#define ADC_5V_C2V(icounts) ((float)icounts * ADC_5V_VOLTS_PER_COUNT + ADC_5V_VOLTS_OFFSET) //Converts 5V Bus counts to volts
#define ADC_5V_V2C(v) (uint16_t)((((float)v - ADC_5V_VOLTS_OFFSET) / ADC_5V_VOLTS_PER_COUNT)) //Converts 5V Bus volts to counts
#define ADC_CC_5VCOR(v5counts, cc) ((float)v5counts == 0 ? 0 : (uint16_t)(ADC_5V_NOMINAL_COUNTS / (float)v5counts * (float)cc)) //Corrects CC counts to nominal 5V value
//Note: The extra port's onboard/external range is not reliable for onboard/external detection due to varying device implementations,
// so instead the extra port will follow the host port connection of onboard or external. We will still use
// a nominal value for device detection with a wider range though.
#define ADC_USBC_ONBOARD 951 //ADC value indicating the USB-C Connector is on main PCB
#define ADC_USBC_EXTERNAL 881 //ADC value indicating the USB-C Connector is on external PCB
#define ADC_USBC_RANGE ((ADC_USBC_ONBOARD - ADC_USBC_EXTERNAL) / 2) //Range of detection for extra port Rd
#define ADC_USBC_EXTRA_NOMINAL ((ADC_USBC_ONBOARD + ADC_USBC_EXTERNAL) / 2) //Nominal ADC value for detection of connected device
#define ADC_USBC_EXTRA_TOLERANCE (0.20f) //Tolerance for Rd
#define ADC_USBC_EXTRA_ADC_MAX ((float)ADC_USBC_EXTRA_NOMINAL + ((float)ADC_USBC_EXTRA_NOMINAL * ADC_USBC_EXTRA_TOLERANCE)) //Rd ADC max counts
#define ADC_USBC_EXTRA_ADC_MIN ((float)ADC_USBC_EXTRA_NOMINAL - ((float)ADC_USBC_EXTRA_NOMINAL * ADC_USBC_EXTRA_TOLERANCE)) //Rd ADC min counts
#define USBC_IS_SINK(a5, b5) ((a5 > ADC_USBC_EXTRA_ADC_MIN && a5 < ADC_USBC_EXTRA_ADC_MAX) || \
(b5 > ADC_USBC_EXTRA_ADC_MIN && b5 < ADC_USBC_EXTRA_ADC_MAX))
#define ADC_USBC_RP_DELTA_MAX 400 //Amount of noise to tolerate for Rp detection (this can be very generous as long as ranges do not overlap)
#define ADC_USBC_RP_TYPES 3 //56k, 22k, 10k
#define ADC_USBC_CON_TYPES 2 //Onboard, External
#define ADC_USBC_TYPES (ADC_USBC_RP_TYPES * ADC_USBC_CON_TYPES)
//These are the indices for ADC_USBC_RP_NOM
//xxK is a ADC_USBC_RP_TYPES
//ONB is for the onboard USB-C Connector and must have an even index number
//EXT is for the external USB-C Connector and must have an odd index number
#define ADC_USBC_56K_ONB 0
#define ADC_USBC_56K_EXT 1
#define ADC_USBC_22K_ONB 2
#define ADC_USBC_22K_EXT 3
#define ADC_USBC_10K_ONB 4
#define ADC_USBC_10K_EXT 5
#define ADC_USBC_IS_ONB(a) (a % 2 == 0) //Given a ADC_USBC_RP_NOM index, return true if the index refers to an onboard connector
#define ADC_USBC_IS_EXT(a) (a % 2 == 1) //Given a ADC_USBC_RP_NOM index, return true if the index refers to an external connector
//These values are for detecting whether or not the host is connected through the onboard USB or external USB
//The counts are calculated from a nominal 5V bus, then scaled depending on the measured 5V bus
//External connectors are detected through addition of a resistor to slightly drop readings while remaining within USB-C CC tolerances
//Set a value to -1 if it is not supported
//Source Rp 56k-Onb 56k-Ext 22k-Onb 22k-Ext 10k-Onb 10k-Ext
#define ADC_USBC_RP_NOM 999, 852, 2232, 1940, 3955, 3528
extern uint16_t adc_usbc_rp_nominal[ADC_USBC_TYPES];
#define POWER_CHECK_INTERVAL 1 //How often to check power usage for adjustment and safety (ms)
#define V_5V_AVGS 20 //Number of 5V readings to average for algorithms wanting stable readings rather than instantaneous

View File

@@ -0,0 +1,139 @@
#ifdef RGB_MATRIX_ENABLE
#include "rocketeer.h"
#include "led_matrix.h"
#include "rgb_matrix.h"
#include "config_led.h"
led_config_t g_led_config = {
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 },
{ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 },
{ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, NO_LED, 40 },
{ 41, NO_LED, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NO_LED, 52 },
{ 53, 54, 55, NO_LED, NO_LED, NO_LED, 56, NO_LED, NO_LED, NO_LED, 57, 58, 59, 60 }
},
{
{ 8, 56 },
{ 22, 56 },
{ 35, 56 },
{ 49, 56 },
{ 63, 56 },
{ 77, 56 },
{ 91, 56 },
{ 105, 56 },
{ 118, 56 },
{ 132, 56 },
{ 146, 56 },
{ 160, 56 },
{ 174, 56 },
{ 195, 56 },
{ 11, 44 },
{ 28, 44 },
{ 42, 44 },
{ 56, 44 },
{ 70, 44 },
{ 84, 44 },
{ 98, 44 },
{ 112, 44 },
{ 125, 44 },
{ 139, 44 },
{ 153, 44 },
{ 167, 44 },
{ 181, 44 },
{ 198, 44 },
{ 13, 32 },
{ 32, 32 },
{ 46, 32 },
{ 60, 32 },
{ 73, 32 },
{ 87, 32 },
{ 101, 32 },
{ 115, 32 },
{ 129, 32 },
{ 143, 32 },
{ 156, 32 },
{ 170, 32 },
// ___
{ 193, 32 },
{ 16, 19 },
{ 39, 19 },
{ 53, 19 },
{ 67, 19 },
{ 80, 19 },
{ 94, 19 },
{ 108, 19 },
{ 122, 19 },
{ 136, 19 },
{ 150, 19 },
{ 163, 19 },
// ___
{ 182, 19 },
{ 9, 7 },
{ 27, 7 },
{ 44, 7 },
// ___
// ___
// ___
{ 96, 7 },
// ___
// ___
// ___
{ 148, 7 },
{ 165, 7 },
{ 188, 7 },
{ 201, 7 },
// Underglow
{ 15, 49 },
{ 35, 49 },
{ 53, 49 },
{ 70, 49 },
{ 88, 49 },
{ 106, 49 },
{ 124, 49 },
{ 142, 49 },
{ 161, 49 },
{ 179, 49 },
{ 197, 49 },
{ 15, 12 },
{ 35, 12 },
{ 53, 12 },
{ 70, 12 },
{ 88, 12 },
{ 106, 12 },
{ 124, 12 },
{ 142, 12 },
{ 161, 12 },
{ 176, 12 },
{ 194, 12 },
{ 15, 37 },
{ 15, 25 },
{ 197, 37 },
{ 197, 25 }
},
{
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1, 1, 1, 4, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2
}
};
#ifdef USB_LED_INDICATOR_ENABLE
void rgb_matrix_indicators_kb(void)
{
led_matrix_indicators();
}
#endif // USB_LED_INDICATOR_ENABLE
#endif

View File

@@ -0,0 +1,160 @@
/*
Copyright 2019 Massdrop Inc.
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
//Define number of IS31FL3733 drivers being used (1...16)
#define ISSI3733_DRIVER_COUNT 2
#define DRIVER_LED_TOTAL ISSI3733_LED_COUNT
//Hardware address of each driver (Refer to IS31FL3733 pdf "Table 1 Slave Address" and keyboard schematic)
#define ISSI3773_DRIVER_ADDRESSES { 0xA0, 0xBE }
//LED I2C bus speed
#define I2C_HZ 580000
//Count of LED bodies
#define ISSI3733_LED_COUNT 87
#define LED_GCR_MAX 165 //Max GCR value (0 - 255) WARNING: Raising this value may overload the LED drivers and USB bus
#define LED_GCR_STEP 10 //GCR increment/decrement value
#ifdef USE_MASSDROP_CONFIGURATOR
#define ANIMATION_SPEED_STEP 1
#define BREATHE_STEP 1
#define BREATHE_MIN_STEP 0
#define BREATHE_MAX_STEP 255
#endif
//Default Global Current Register value (Default brightness 0 - 255)
#define ISSI3733_GCR_DEFAULT LED_GCR_MAX
//Automatic power rollback and recovery
#define V5_HIGH 2494 //5V high level (After low power detect, point at which LEDs are allowed to use more power )
#define V5_LOW 2434 //5V low level (LED power rolled back to stay above this limit)
#define V5_CAT 2206 //5V catastrophic level (Host USB port potential to shut down)
//LED Mapping - More practically generated from a spreadsheet program
//id: ID of the LED (Sync with PCB callouts)
//x: Physical X coordinate of LED (units do not matter)
//y: Physical Y coordinate of LED (units do not matter)
//drv: 1-Based index of ISSI3773_DRIVER_ADDRESSES
//cs: Matrix wiring CS col (1-16)
//swr: Matrix wiring SW Red row (1-12)
//swg: Matrix wiring SW Green row (1-12)
//swb: Matrix wiring SW Blue row (1-12)
//scan: Associated key matrix scancode (set 255 if none or 254 for LED to turn off in alternating mode)
//Note: Origin 0,0 may be located anywhere as the software will do the final layout
#define ISSI3733_LED_MAP { \
{ .id = 1, .x = 0.36, .y = 3.362, .adr = { .drv = 2, .cs = 9, .swr = 2, .swg = 1, .swb = 3 }, .scan = 0 }, \
{ .id = 2, .x = 1.11, .y = 3.362, .adr = { .drv = 2, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 1 }, \
{ .id = 3, .x = 1.86, .y = 3.362, .adr = { .drv = 2, .cs = 8, .swr = 5, .swg = 4, .swb = 6 }, .scan = 2 }, \
{ .id = 4, .x = 2.61, .y = 3.362, .adr = { .drv = 2, .cs = 7, .swr = 2, .swg = 1, .swb = 3 }, .scan = 3 }, \
{ .id = 5, .x = 3.36, .y = 3.362, .adr = { .drv = 2, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 4 }, \
{ .id = 6, .x = 4.11, .y = 3.362, .adr = { .drv = 2, .cs = 5, .swr = 5, .swg = 4, .swb = 6 }, .scan = 5 }, \
{ .id = 7, .x = 4.86, .y = 3.362, .adr = { .drv = 2, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 6 }, \
{ .id = 8, .x = 5.61, .y = 3.362, .adr = { .drv = 1, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 7 }, \
{ .id = 9, .x = 6.36, .y = 3.362, .adr = { .drv = 1, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 8 }, \
{ .id = 10, .x = 7.11, .y = 3.362, .adr = { .drv = 1, .cs = 9, .swr = 2, .swg = 1, .swb = 3 }, .scan = 9 }, \
{ .id = 11, .x = 7.86, .y = 3.362, .adr = { .drv = 1, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 10 }, \
{ .id = 12, .x = 8.61, .y = 3.362, .adr = { .drv = 1, .cs = 7, .swr = 2, .swg = 1, .swb = 3 }, .scan = 11 }, \
{ .id = 13, .x = 9.36, .y = 3.362, .adr = { .drv = 1, .cs = 7, .swr = 5, .swg = 4, .swb = 6 }, .scan = 12 }, \
{ .id = 14, .x = 10.485, .y = 3.362, .adr = { .drv = 1, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 13 }, \
{ .id = 15, .x = 0.548, .y = 2.612, .adr = { .drv = 2, .cs = 9, .swr = 8, .swg = 7, .swb = 9 }, .scan = 14 }, \
{ .id = 16, .x = 1.485, .y = 2.612, .adr = { .drv = 2, .cs = 8, .swr = 11, .swg = 10, .swb = 12 }, .scan = 15 }, \
{ .id = 17, .x = 2.235, .y = 2.612, .adr = { .drv = 2, .cs = 7, .swr = 8, .swg = 7, .swb = 9 }, .scan = 16 }, \
{ .id = 18, .x = 2.985, .y = 2.612, .adr = { .drv = 2, .cs = 7, .swr = 11, .swg = 10, .swb = 12 }, .scan = 17 }, \
{ .id = 19, .x = 3.735, .y = 2.612, .adr = { .drv = 2, .cs = 5, .swr = 11, .swg = 10, .swb = 12 }, .scan = 18 }, \
{ .id = 20, .x = 4.485, .y = 2.612, .adr = { .drv = 2, .cs = 3, .swr = 5, .swg = 4, .swb = 6 }, .scan = 19 }, \
{ .id = 21, .x = 5.235, .y = 2.612, .adr = { .drv = 2, .cs = 3, .swr = 11, .swg = 10, .swb = 12 }, .scan = 20 }, \
{ .id = 22, .x = 5.985, .y = 2.612, .adr = { .drv = 1, .cs = 12, .swr = 8, .swg = 7, .swb = 9 }, .scan = 21 }, \
{ .id = 23, .x = 6.735, .y = 2.612, .adr = { .drv = 1, .cs = 11, .swr = 8, .swg = 7, .swb = 9 }, .scan = 22 }, \
{ .id = 24, .x = 7.485, .y = 2.612, .adr = { .drv = 1, .cs = 9, .swr = 8, .swg = 7, .swb = 9 }, .scan = 23 }, \
{ .id = 25, .x = 8.235, .y = 2.612, .adr = { .drv = 1, .cs = 8, .swr = 8, .swg = 7, .swb = 9 }, .scan = 24 }, \
{ .id = 26, .x = 8.985, .y = 2.612, .adr = { .drv = 1, .cs = 7, .swr = 8, .swg = 7, .swb = 9 }, .scan = 25 }, \
{ .id = 27, .x = 9.735, .y = 2.612, .adr = { .drv = 1, .cs = 5, .swr = 11, .swg = 10, .swb = 12 }, .scan = 26 }, \
{ .id = 28, .x = 10.673, .y = 2.612, .adr = { .drv = 1, .cs = 3, .swr = 5, .swg = 4, .swb = 6 }, .scan = 27 }, \
{ .id = 29, .x = 0.641, .y = 1.862, .adr = { .drv = 2, .cs = 11, .swr = 11, .swg = 10, .swb = 12 }, .scan = 28 }, \
{ .id = 30, .x = 1.673, .y = 1.862, .adr = { .drv = 2, .cs = 11, .swr = 8, .swg = 7, .swb = 9 }, .scan = 29 }, \
{ .id = 31, .x = 2.423, .y = 1.862, .adr = { .drv = 2, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 30 }, \
{ .id = 32, .x = 3.173, .y = 1.862, .adr = { .drv = 2, .cs = 11, .swr = 5, .swg = 4, .swb = 6 }, .scan = 31 }, \
{ .id = 33, .x = 3.923, .y = 1.862, .adr = { .drv = 2, .cs = 2, .swr = 5, .swg = 4, .swb = 6 }, .scan = 32 }, \
{ .id = 34, .x = 4.673, .y = 1.862, .adr = { .drv = 2, .cs = 2, .swr = 8, .swg = 7, .swb = 9 }, .scan = 33 }, \
{ .id = 35, .x = 5.423, .y = 1.862, .adr = { .drv = 2, .cs = 2, .swr = 11, .swg = 10, .swb = 12 }, .scan = 34 }, \
{ .id = 36, .x = 6.173, .y = 1.862, .adr = { .drv = 1, .cs = 12, .swr = 11, .swg = 10, .swb = 12 }, .scan = 35 }, \
{ .id = 37, .x = 6.923, .y = 1.862, .adr = { .drv = 1, .cs = 11, .swr = 11, .swg = 10, .swb = 12 }, .scan = 36 }, \
{ .id = 38, .x = 7.673, .y = 1.862, .adr = { .drv = 1, .cs = 9, .swr = 11, .swg = 10, .swb = 12 }, .scan = 37 }, \
{ .id = 39, .x = 8.423, .y = 1.862, .adr = { .drv = 1, .cs = 8, .swr = 11, .swg = 10, .swb = 12 }, .scan = 38 }, \
{ .id = 40, .x = 9.173, .y = 1.862, .adr = { .drv = 1, .cs = 7, .swr = 11, .swg = 10, .swb = 12 }, .scan = 39 }, \
{ .id = 41, .x = 10.391, .y = 1.862, .adr = { .drv = 1, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 41 }, \
{ .id = 42, .x = 0.829, .y = 1.112, .adr = { .drv = 2, .cs = 12, .swr = 8, .swg = 7, .swb = 9 }, .scan = 42 }, \
{ .id = 43, .x = 2.048, .y = 1.112, .adr = { .drv = 2, .cs = 13, .swr = 11, .swg = 10, .swb = 12 }, .scan = 44 }, \
{ .id = 44, .x = 2.798, .y = 1.112, .adr = { .drv = 2, .cs = 14, .swr = 11, .swg = 10, .swb = 12 }, .scan = 45 }, \
{ .id = 45, .x = 3.548, .y = 1.112, .adr = { .drv = 2, .cs = 14, .swr = 8, .swg = 7, .swb = 9 }, .scan = 46 }, \
{ .id = 46, .x = 4.298, .y = 1.112, .adr = { .drv = 2, .cs = 16, .swr = 8, .swg = 7, .swb = 9 }, .scan = 47 }, \
{ .id = 47, .x = 5.048, .y = 1.112, .adr = { .drv = 2, .cs = 16, .swr = 11, .swg = 10, .swb = 12 }, .scan = 48 }, \
{ .id = 48, .x = 5.798, .y = 1.112, .adr = { .drv = 1, .cs = 13, .swr = 11, .swg = 10, .swb = 12 }, .scan = 49 }, \
{ .id = 49, .x = 6.548, .y = 1.112, .adr = { .drv = 1, .cs = 13, .swr = 8, .swg = 7, .swb = 9 }, .scan = 50 }, \
{ .id = 50, .x = 7.298, .y = 1.112, .adr = { .drv = 1, .cs = 14, .swr = 8, .swg = 7, .swb = 9 }, .scan = 51 }, \
{ .id = 51, .x = 8.048, .y = 1.112, .adr = { .drv = 1, .cs = 14, .swr = 11, .swg = 10, .swb = 12 }, .scan = 52 }, \
{ .id = 52, .x = 8.798, .y = 1.112, .adr = { .drv = 1, .cs = 16, .swr = 11, .swg = 10, .swb = 12 }, .scan = 53 }, \
{ .id = 53, .x = 10.204, .y = 1.112, .adr = { .drv = 1, .cs = 2, .swr = 11, .swg = 10, .swb = 12 }, .scan = 55 }, \
{ .id = 54, .x = 0.454, .y = 0.362, .adr = { .drv = 2, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 56 }, \
{ .id = 55, .x = 1.391, .y = 0.362, .adr = { .drv = 2, .cs = 13, .swr = 2, .swg = 1, .swb = 3 }, .scan = 57 }, \
{ .id = 56, .x = 2.329, .y = 0.362, .adr = { .drv = 2, .cs = 13, .swr = 5, .swg = 4, .swb = 6 }, .scan = 58 }, \
{ .id = 57, .x = 5.141, .y = 0.362, .adr = { .drv = 2, .cs = 16, .swr = 2, .swg = 1, .swb = 3 }, .scan = 62 }, \
{ .id = 58, .x = 7.954, .y = 0.362, .adr = { .drv = 1, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 66 }, \
{ .id = 59, .x = 8.891, .y = 0.362, .adr = { .drv = 1, .cs = 16, .swr = 2, .swg = 1, .swb = 3 }, .scan = 67 }, \
{ .id = 60, .x = 9.829, .y = 0.362, .adr = { .drv = 1, .cs = 2, .swr = 8, .swg = 7, .swb = 9 }, .scan = 68 }, \
{ .id = 61, .x = 10.766, .y = 0.362, .adr = { .drv = 1, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 69 }, \
{ .id = 62, .x = 0.74, .y = 3, .adr = { .drv = 2, .cs = 9, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 63, .x = 1.714, .y = 3, .adr = { .drv = 2, .cs = 8, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 64, .x = 2.688, .y = 3, .adr = { .drv = 2, .cs = 7, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 65, .x = 3.662, .y = 3, .adr = { .drv = 2, .cs = 5, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 66, .x = 4.636, .y = 3, .adr = { .drv = 2, .cs = 3, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 67, .x = 5.61, .y = 3, .adr = { .drv = 1, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 68, .x = 6.584, .y = 3, .adr = { .drv = 1, .cs = 11, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 69, .x = 7.558, .y = 3, .adr = { .drv = 1, .cs = 9, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 70, .x = 8.532, .y = 3, .adr = { .drv = 1, .cs = 8, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 71, .x = 9.506, .y = 3, .adr = { .drv = 1, .cs = 5, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 72, .x = 10.48, .y = 3, .adr = { .drv = 1, .cs = 5, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 73, .x = 0.74, .y = 0.74, .adr = { .drv = 2, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 74, .x = 1.714, .y = 0.74, .adr = { .drv = 2, .cs = 13, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 75, .x = 2.688, .y = 0.74, .adr = { .drv = 2, .cs = 14, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 76, .x = 3.662, .y = 0.74, .adr = { .drv = 2, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 77, .x = 4.636, .y = 0.74, .adr = { .drv = 2, .cs = 16, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 78, .x = 5.61, .y = 0.74, .adr = { .drv = 1, .cs = 13, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 79, .x = 6.584, .y = 0.74, .adr = { .drv = 1, .cs = 13, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 80, .x = 7.558, .y = 0.74, .adr = { .drv = 1, .cs = 14, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 81, .x = 8.532, .y = 0.74, .adr = { .drv = 1, .cs = 16, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 82, .x = 9.506, .y = 0.74, .adr = { .drv = 1, .cs = 16, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 83, .x = 10.48, .y = 0.74, .adr = { .drv = 1, .cs = 2, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 84, .x = 0.74, .y = 2.25, .adr = { .drv = 2, .cs = 9, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 85, .x = 0.74, .y = 1.5, .adr = { .drv = 2, .cs = 12, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 86, .x = 10.48, .y = 2.25, .adr = { .drv = 1, .cs = 3, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 87, .x = 10.48, .y = 1.5, .adr = { .drv = 1, .cs = 3, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
};
#define USB_LED_INDICATOR_ENABLE //Comment out to disable indicator functionality
#ifdef USB_LED_INDICATOR_ENABLE //Scan codes refer to actual key matrix codes, not KC_* (255 to disable)
#define USB_LED_NUM_LOCK_SCANCODE 255
#define USB_LED_CAPS_LOCK_SCANCODE 28
#define USB_LED_SCROLL_LOCK_SCANCODE 21
#define USB_LED_COMPOSE_SCANCODE 255
#define USB_LED_KANA_SCANCODE 255
#endif //USB_LED_INDICATOR_ENABLE

View File

@@ -0,0 +1,42 @@
/*
Copyright 2019 Massdrop Inc.
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
/* Data structure to define Shift Register output expander hardware */
/* This structure gets shifted into registers LSB first */
typedef union {
struct {
uint16_t RSVD4:1; /*!< bit: 0 */
uint16_t SRC_2_B5:1; /*!< bit: 1 USBC-2 CC B5 UFP Rd 5.1k WHEN 1, DFP Rp 56k WHEN 0 */
uint16_t SRC_1_B5:1; /*!< bit: 2 USBC-1 CC B5 UFP Rd 5.1k WHEN 1, DFP Rp 56k WHEN 0 */
uint16_t S_B_EXT:1; /*!< bit: 3 B TO EX-1 WHEN 0, B TO USBC-1 WHEN 1 */
uint16_t SDB_N:1; /*!< bit: 4 SHUTDOWN IS31FL3733 CHIPS WHEN 0, RUN WHEN 1 */
uint16_t IRST:1; /*!< bit: 5 RESET IS31FL3733 I2C WHEN 1, RUN WHEN 0 */
uint16_t SRC_2_A5:1; /*!< bit: 6 USBC-2 CC A5 UFP Rd 5.1k WHEN 1, DFP Rp 56k WHEN 0 */
uint16_t SRC_1_A5:1; /*!< bit: 7 USBC-1 CC A5 UFP Rd 5.1k WHEN 1, DFP Rp 56k WHEN 0 */
uint16_t E_VBUS_2:1; /*!< bit: 8 ENABLE 5V TO USBC-2/EX-2 WHEN 1, DISABLE WHEN 0 */
uint16_t E_VBUS_1:1; /*!< bit: 9 ENABLE 5V TO USBC-1/EX-1 WHEN 1, DISABLE WHEN 0 */
uint16_t ENB:1; /*!< bit: 10 ENABLE CHANNEL B USBC-1/EX-1 WHEN 1, DISABLE WHEN 0 */
uint16_t S_A_EXT:1; /*!< bit: 11 A TO USBC-2 WHEN 0, A TO EX-2 WHEN 1 */
uint16_t ENA:1; /*!< bit: 12 ENABLE CHANNEL A USBC-2/EX-2 WHEN 1, DISABLE WHEN 0 */
uint16_t S_A_UP:1; /*!< bit: 13 DN1 TO A & UP TO B WHEN 1, DN1 TO B & UP TO A WHEN 0 */
uint16_t HUB_RESET_N:1; /*!< bit: 14 RESET USB HUB WHEN 0, RUN WHEN 1 */
uint16_t HUB_CONNECT:1; /*!< bit: 15 SIGNAL VBUS CONNECT TO USB HUB WHEN 1 */
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} sr_exp_t;

View File

@@ -0,0 +1,28 @@
/*
Copyright 2019 Massdrop Inc.
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
//Macros to Enable, Disable, and Update USB 5V bus connections
#define USBC_CFG_5V1_VAR sr_exp_data.bit.E_VBUS_1 //Variable storing USBC-1 5V Bus state
#define USBC_CFG_5V1_ENA 1 //Value to enable USBC-1 5V Bus
#define USBC_CFG_5V1_DIS 0 //Value to disable USBC-1 5V Bus
#define USBC_CFG_5V1_UPDATE SR_EXP_WriteData() //Command to run to update value
#define USBC_CFG_5V2_VAR sr_exp_data.bit.E_VBUS_2 //Variable storing USBC-2 5V Bus state
#define USBC_CFG_5V2_ENA 1 //Value to enable USBC-1 5V Bus
#define USBC_CFG_5V2_DIS 0 //Value to disable USBC-1 5V Bus
#define USBC_CFG_5V2_UPDATE SR_EXP_WriteData() //Command to run to update value

View File

@@ -0,0 +1,286 @@
#include QMK_KEYBOARD_H
enum rocketeer_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase
L_BRD, //LED Brightness Decrease
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next
L_PTP, //LED Pattern Select Previous
L_PSI, //LED Pattern Speed Increase
L_PSD, //LED Pattern Speed Decrease
L_T_MD, //LED Toggle Mode
L_T_ONF, //LED Toggle On / Off
L_ON, //LED On
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction and effect
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
DBG_FAC, //DEBUG Factory light testing (All on white)
MD_BOOT //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
keymap_config_t keymap_config;
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
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_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_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_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, \
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RGUI, KC_RCTL \
),
[1] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
L_T_BR, L_PSD, L_BRI, L_PSI, L_EDG_I, _______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_UP, _______, _______, U_T_AGCR,\
L_T_PTD, L_PTP, L_BRD, L_PTN, L_EDG_D, _______, KC_INS, KC_HOME, KC_PGUP, KC_LEFT, KC_DOWN, KC_RGHT, _______, \
_______, L_T_MD, L_T_ONF, _______, L_EDG_M, MD_BOOT, TG_NKRO, KC_END, KC_PGDN, KC_VOLD, KC_VOLU, _______, \
_______, _______, _______, DBG_FAC, KC_MUTE, _______, KC_APP, _______ \
),
/*
[X] = LAYOUT(
_______ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______ \
),
*/
};
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
static uint8_t scroll_effect = 0;
switch (keycode) {
case L_BRI:
if (record->event.pressed) {
if (LED_GCR_STEP > LED_GCR_MAX - gcr_desired) gcr_desired = LED_GCR_MAX;
else gcr_desired += LED_GCR_STEP;
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_BRD:
if (record->event.pressed) {
if (LED_GCR_STEP > gcr_desired) gcr_desired = 0;
else gcr_desired -= LED_GCR_STEP;
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_EDG_M:
if (record->event.pressed) {
led_edge_mode++;
if (led_edge_mode > LED_EDGE_MODE_MAX) {
led_edge_mode = LED_EDGE_MODE_ALL;
}
}
return false;
case L_EDG_I:
if (record->event.pressed) {
led_edge_brightness += 0.1;
if (led_edge_brightness > 1) { led_edge_brightness = 1; }
}
return false;
case L_EDG_D:
if (record->event.pressed) {
led_edge_brightness -= 0.1;
if (led_edge_brightness < 0) { led_edge_brightness = 0; }
}
return false;
case L_PTN:
if (record->event.pressed) {
if (led_animation_id == led_setups_count - 1) led_animation_id = 0;
else led_animation_id++;
}
return false;
case L_PTP:
if (record->event.pressed) {
if (led_animation_id == 0) led_animation_id = led_setups_count - 1;
else led_animation_id--;
}
return false;
case L_PSI:
if (record->event.pressed) {
led_animation_speed += ANIMATION_SPEED_STEP;
}
return false;
case L_PSD:
if (record->event.pressed) {
led_animation_speed -= ANIMATION_SPEED_STEP;
if (led_animation_speed < 0) led_animation_speed = 0;
}
return false;
case L_T_MD:
if (record->event.pressed) {
led_lighting_mode++;
if (led_lighting_mode > LED_MODE_MAX_INDEX) led_lighting_mode = LED_MODE_NORMAL;
}
return false;
case L_T_ONF:
if (record->event.pressed) {
I2C3733_Control_Set(!I2C3733_Control_Get());
}
return false;
case L_ON:
if (record->event.pressed) {
I2C3733_Control_Set(1);
}
return false;
case L_OFF:
if (record->event.pressed) {
I2C3733_Control_Set(0);
}
return false;
case L_T_BR:
if (record->event.pressed) {
led_animation_breathing = !led_animation_breathing;
if (led_animation_breathing) {
gcr_breathe = gcr_desired;
led_animation_breathe_cur = BREATHE_MIN_STEP;
breathe_dir = 1;
}
}
return false;
case L_T_PTD:
if (record->event.pressed) {
scroll_effect++;
if (scroll_effect == 1) { //Patterns with scroll move horizontal (Right to left)
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 0;
} else if (scroll_effect == 2) { //Patterns with scroll move vertical (Top to bottom)
led_animation_direction = 1;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 3) { //Patterns with scroll move vertical (Bottom to top)
led_animation_direction = 0;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 4) { //Patterns with scroll explode from center
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 1;
} else if (scroll_effect == 5) { //Patterns with scroll implode on center
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 1;
} else { //Patterns with scroll move horizontal (Left to right)
scroll_effect = 0;
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 0;
}
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_FAC:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
led_lighting_mode = LED_MODE_NORMAL;
led_edge_brightness = 1;
led_edge_mode = LED_EDGE_MODE_ALL;
led_animation_breathing = 0;
led_animation_id = 7; //led_programs.c led_setups leds_white index
gcr_desired = LED_GCR_MAX;
I2C3733_Control_Set(1);
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
}
return false;
case DBG_MTRX:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_matrix, "Debug matrix");
}
return false;
case DBG_KBD:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_keyboard, "Debug keyboard");
}
return false;
case DBG_MOU:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_mouse, "Debug mouse");
}
return false;
case MD_BOOT:
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}
return false;
default:
return true; //Process all other keycodes normally
}
}
void rgb_matrix_init_user(void) {
led_lighting_mode = LED_MODE_INDICATORS_ONLY; //Start Rocketeer with only indicator lights
}
led_instruction_t led_instructions[] = {
//LEDs are normally inactive, no processing is performed on them
//Flags are used in matching criteria for an LED to be active and indicate how to color it
//Flags can be found in tmk_core/protocol/arm_atsam/led_matrix.h (prefixed with LED_FLAG_)
//LED IDs can be found in config_led.h in the keyboard's directory
//Examples are below
//All LEDs use the user's selected pattern (this is the factory default)
{ .flags = LED_FLAG_USE_ROTATE_PATTERN },
//Specific LEDs use the user's selected pattern while all others are off
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_ROTATE_PATTERN, .id0 = 0xFFFFFFFF, .id1 = 0xAAAAAAAA, .id2 = 0x55555555, .id3 = 0x11111111 },
//Specific LEDs use specified RGB values while all others are off
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0xFF, .id1 = 0x00FF, .id2 = 0x0000FF00, .id3 = 0xFF000000, .r = 75, .g = 150, .b = 225 },
//All LEDs use the user's selected pattern
//On layer 1, all key LEDs (except the top row which keeps active pattern) are red while all edge LEDs are green
//When layer 1 is active, key LEDs use red (id0 32 - 17: 1111 1111 1111 1111 0000 0000 0000 0000 = 0xFFFF0000) (except top row 16 - 1)
//When layer 1 is active, key LEDs use red (id1 64 - 33: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
//When layer 1 is active, key LEDs use red (id2 87 - 65: 0000 0000 0111 1111 1111 1111 1111 1111 = 0x007FFFFF)
//When layer 1 is active, edge LEDs use green (id2 95 - 88: 1111 1111 1000 0000 0000 0000 0000 0000 = 0xFF800000)
//When layer 1 is active, edge LEDs use green (id3 119 - 96: 0000 0000 1111 1111 1111 1111 1111 1111 = 0x00FFFFFF)
// { .flags = LED_FLAG_USE_ROTATE_PATTERN },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_MATCH_LAYER | LED_FLAG_USE_RGB, .id0 = 0xFFFF0000, .id1 = 0xFFFFFFFF, .id2 = 0x007FFFFF, .r = 255, .layer = 1 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_MATCH_LAYER | LED_FLAG_USE_RGB, .id2 = 0xFF800000, .id3 = 0x00FFFFFF, .g = 127, .layer = 1 },
//All key LEDs use red while edge LEDs use the active pattern
//All key LEDs use red (id0 32 - 1: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
//All key LEDs use red (id1 64 - 33: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
//All key LEDs use red (id2 87 - 65: 0000 0000 0111 1111 1111 1111 1111 1111 = 0x007FFFFF)
//Edge uses active pattern (id2 95 - 88: 1111 1111 1000 0000 0000 0000 0000 0000 = 0xFF800000)
//Edge uses active pattern (id3 119 - 96: 0000 0000 1111 1111 1111 1111 1111 1111 = 0x00FFFFFF)
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0xFFFFFFFF, .id1 = 0xFFFFFFFF, .id2 = 0x007FFFFF, .r = 255 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_ROTATE_PATTERN , .id2 = 0xFF800000, .id3 = 0x00FFFFFF },
//end must be set to 1 to indicate end of instruction set
{ .end = 1 }
};

View File

@@ -0,0 +1,2 @@
# This keymap requires Massdrop Configurator support
OPT_DEFS += -DUSE_MASSDROP_CONFIGURATOR

View File

@@ -0,0 +1,256 @@
#include QMK_KEYBOARD_H
enum rocketeer_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase
L_BRD, //LED Brightness Decrease
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next
L_PTP, //LED Pattern Select Previous
L_PSI, //LED Pattern Speed Increase
L_PSD, //LED Pattern Speed Decrease
L_T_MD, //LED Toggle Mode
L_T_ONF, //LED Toggle On / Off
L_ON, //LED On
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction and effect
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
DBG_FAC, //DEBUG Factory light testing (All on white)
MD_BOOT //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
keymap_config_t keymap_config;
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
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_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_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_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, \
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(1), KC_APP, KC_RCTL \
),
[1] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
L_T_BR, L_PSD, L_BRI, L_PSI, L_EDG_I, _______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_UP, _______, _______, U_T_AGCR,\
L_T_PTD, L_PTP, L_BRD, L_PTN, L_EDG_D, _______, KC_INS, KC_HOME, KC_PGUP, KC_LEFT, KC_DOWN, KC_RGHT, _______, \
_______, L_T_MD, L_T_ONF, _______, L_EDG_M, MD_BOOT, TG_NKRO, KC_END, KC_PGDN, KC_VOLD, KC_VOLU, _______, \
_______, _______, _______, DBG_FAC, KC_MUTE, _______, _______, _______ \
),
/*
[X] = LAYOUT(
_______ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______ \
),
*/
};
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
static uint8_t scroll_effect = 0;
switch (keycode) {
case L_BRI:
if (record->event.pressed) {
if (LED_GCR_STEP > LED_GCR_MAX - gcr_desired) gcr_desired = LED_GCR_MAX;
else gcr_desired += LED_GCR_STEP;
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_BRD:
if (record->event.pressed) {
if (LED_GCR_STEP > gcr_desired) gcr_desired = 0;
else gcr_desired -= LED_GCR_STEP;
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_EDG_M:
if (record->event.pressed) {
led_edge_mode++;
if (led_edge_mode > LED_EDGE_MODE_MAX) {
led_edge_mode = LED_EDGE_MODE_ALL;
}
}
return false;
case L_EDG_I:
if (record->event.pressed) {
led_edge_brightness += 0.1;
if (led_edge_brightness > 1) { led_edge_brightness = 1; }
}
return false;
case L_EDG_D:
if (record->event.pressed) {
led_edge_brightness -= 0.1;
if (led_edge_brightness < 0) { led_edge_brightness = 0; }
}
return false;
case L_PTN:
if (record->event.pressed) {
if (led_animation_id == led_setups_count - 1) led_animation_id = 0;
else led_animation_id++;
}
return false;
case L_PTP:
if (record->event.pressed) {
if (led_animation_id == 0) led_animation_id = led_setups_count - 1;
else led_animation_id--;
}
return false;
case L_PSI:
if (record->event.pressed) {
led_animation_speed += ANIMATION_SPEED_STEP;
}
return false;
case L_PSD:
if (record->event.pressed) {
led_animation_speed -= ANIMATION_SPEED_STEP;
if (led_animation_speed < 0) led_animation_speed = 0;
}
return false;
case L_T_MD:
if (record->event.pressed) {
led_lighting_mode++;
if (led_lighting_mode > LED_MODE_MAX_INDEX) led_lighting_mode = LED_MODE_NORMAL;
}
return false;
case L_T_ONF:
if (record->event.pressed) {
I2C3733_Control_Set(!I2C3733_Control_Get());
}
return false;
case L_ON:
if (record->event.pressed) {
I2C3733_Control_Set(1);
}
return false;
case L_OFF:
if (record->event.pressed) {
I2C3733_Control_Set(0);
}
return false;
case L_T_BR:
if (record->event.pressed) {
led_animation_breathing = !led_animation_breathing;
if (led_animation_breathing) {
gcr_breathe = gcr_desired;
led_animation_breathe_cur = BREATHE_MIN_STEP;
breathe_dir = 1;
}
}
return false;
case L_T_PTD:
if (record->event.pressed) {
scroll_effect++;
if (scroll_effect == 1) { //Patterns with scroll move horizontal (Right to left)
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 0;
} else if (scroll_effect == 2) { //Patterns with scroll move vertical (Top to bottom)
led_animation_direction = 1;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 3) { //Patterns with scroll move vertical (Bottom to top)
led_animation_direction = 0;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 4) { //Patterns with scroll explode from center
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 1;
} else if (scroll_effect == 5) { //Patterns with scroll implode on center
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 1;
} else { //Patterns with scroll move horizontal (Left to right)
scroll_effect = 0;
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 0;
}
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_FAC:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
led_lighting_mode = LED_MODE_NORMAL;
led_edge_brightness = 1;
led_edge_mode = LED_EDGE_MODE_ALL;
led_animation_breathing = 0;
led_animation_id = 7; //led_programs.c led_setups leds_white index
gcr_desired = LED_GCR_MAX;
I2C3733_Control_Set(1);
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
}
return false;
case DBG_MTRX:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_matrix, "Debug matrix");
}
return false;
case DBG_KBD:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_keyboard, "Debug keyboard");
}
return false;
case DBG_MOU:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_mouse, "Debug mouse");
}
return false;
case MD_BOOT:
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}
return false;
default:
return true; //Process all other keycodes normally
}
}
void rgb_matrix_init_user(void) {
led_lighting_mode = LED_MODE_INDICATORS_ONLY; //Start Rocketeer with only indicator lights
}
led_instruction_t led_instructions[] = {
//Please see ../default_md/keymap.c for examples
//All LEDs use the user's selected pattern (this is the factory default)
{ .flags = LED_FLAG_USE_ROTATE_PATTERN },
//end must be set to 1 to indicate end of instruction set
{ .end = 1 }
};

View File

@@ -0,0 +1,2 @@
# This keymap requires Massdrop Configurator support
OPT_DEFS += -DUSE_MASSDROP_CONFIGURATOR

View File

@@ -0,0 +1,182 @@
/*
Copyright 2019 Massdrop Inc.
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 "rocketeer.h"
#include "d51_util.h"
#include "debug.h"
#include "clks.h"
#include <string.h>
#define MCU_PORTS_USED 2 //PA, PB
matrix_row_t mlatest[MATRIX_ROWS];
matrix_row_t mlast[MATRIX_ROWS];
matrix_row_t mdebounced[MATRIX_ROWS];
uint8_t row_ports[] = { MATRIX_ROW_PORTS };
uint8_t row_pins[] = { MATRIX_ROW_PINS };
uint8_t col_ports[] = { MATRIX_COL_PORTS };
uint8_t col_pins[] = { MATRIX_COL_PINS };
uint32_t row_masks[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
__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) {
}
void matrix_init(void)
{
memset(mlatest, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(mlast, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(mdebounced, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(row_masks, 0, sizeof(row_masks));
//Inputs
uint8_t row;
for (row = 0; row < MATRIX_ROWS; row++)
{
PORT->Group[row_ports[row]].DIRCLR.reg = 1 << row_pins[row]; //Input
PORT->Group[row_ports[row]].OUTCLR.reg = 1 << row_pins[row]; //Low
PORT->Group[row_ports[row]].PINCFG[row_pins[row]].bit.INEN = 1; //Input Enable,
PORT->Group[row_ports[row]].PINCFG[row_pins[row]].bit.PULLEN = 1; //Pull Enable
row_masks[row_ports[row]] |= 1 << row_pins[row]; //Add pin to proper row mask
}
//Outputs
uint8_t col;
for (col = 0; col < MATRIX_COLS; col++)
{
PORT->Group[col_ports[col]].DIRSET.reg = 1 << col_pins[col]; //Output
PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Low
}
matrix_init_quantum();
}
uint64_t mdebouncing = 0;
bool debouncing = false;
uint8_t matrix_scan(void)
{
uint64_t timer;
uint8_t row;
uint8_t col;
uint32_t scans[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
memset(mlatest, 0, MATRIX_ROWS * sizeof(matrix_row_t)); //Zero the result buffer
for (col = 0; col < MATRIX_COLS; col++)
{
//Set output
PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; //Set col output
wait_us(1); //Delay for output
//Read input (add unique ports as needed, PA, PB, PC, etc)
scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; //Read PA row pins data
scans[PB] = PORT->Group[PB].IN.reg & row_masks[PB]; //Read PA row pins data
//Clear output
PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Clear col output
for (row = 0; row < MATRIX_ROWS; row++)
{
//Move scan bits from scans array into proper row bit locations
if (scans[row_ports[row]] & (1 << row_pins[row]))
mlatest[row] |= 1 << col;
}
}
timer = timer_read64();
for (row = 0; row < MATRIX_ROWS; row++)
{
if (mlast[row] != mlatest[row]) {
debouncing = true;
mdebouncing = timer + DEBOUNCE;
}
mlast[row] = mlatest[row];
}
if (debouncing && timer >= mdebouncing)
{
for (row = 0; row < MATRIX_ROWS; row++) {
mdebounced[row] = mlatest[row];
}
mdebouncing = 0;
debouncing = false;
}
matrix_scan_quantum();
return 1;
}
matrix_row_t matrix_get_row(uint8_t row)
{
return mdebounced[row];
}
void matrix_print(void)
{
char buf[(MATRIX_COLS+8)*(MATRIX_ROWS+1)] = "R C";
char *pbuf = buf+3;
uint32_t cols;
uint32_t rows;
matrix_row_t row;
for (cols = 1; cols <= MATRIX_COLS; cols++)
{
*pbuf = (cols%10)+48;
pbuf++;
}
*pbuf = '\r'; pbuf++;
*pbuf = '\n'; pbuf++;
for (rows = 1; rows <= MATRIX_ROWS; rows++)
{
row = matrix_get_row(rows-1);
if (rows < 10) { *pbuf = rows+48; pbuf++; *pbuf = ' '; pbuf++; *pbuf = ' '; pbuf++; }
else { *pbuf = (rows/10)+48; pbuf++; *pbuf = (rows%10)+48; pbuf++; *pbuf = ' '; pbuf++; }
for (cols = 0; cols < MATRIX_COLS; cols++)
{
if (row & 1 << cols) *pbuf = 'X';
else *pbuf = '.';
pbuf++;
}
*pbuf = '\r'; pbuf++;
*pbuf = '\n'; pbuf++;
}
*pbuf = 0;
dprint(buf);
}

View File

@@ -0,0 +1,77 @@
/*
Copyright 2011 Jun Wako <wakojun@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/>.
*/
#ifndef MATRIX_H
#define MATRIX_H
#include <stdint.h>
#include <stdbool.h>
#include "keyboard.h"
#if (MATRIX_COLS <= 8)
typedef uint8_t matrix_row_t;
#elif (MATRIX_COLS <= 16)
typedef uint16_t matrix_row_t;
#elif (MATRIX_COLS <= 32)
typedef uint32_t matrix_row_t;
#else
#error "MATRIX_COLS: invalid value"
#endif
#define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col))
#ifdef __cplusplus
extern "C" {
#endif
/* number of matrix rows */
uint8_t matrix_rows(void);
/* number of matrix columns */
uint8_t matrix_cols(void);
/* should be called at early stage of startup before matrix_init.(optional) */
void matrix_setup(void);
/* intialize matrix for scaning. */
void matrix_init(void);
/* scan all key states on matrix */
uint8_t matrix_scan(void);
/* whether modified from previous scan. used after matrix_scan. */
bool matrix_is_modified(void) __attribute__ ((deprecated));
/* whether a switch is on */
bool matrix_is_on(uint8_t row, uint8_t col);
/* matrix state on row */
matrix_row_t matrix_get_row(uint8_t row);
/* print matrix for debug */
void matrix_print(void);
/* power control */
void matrix_power_up(void);
void matrix_power_down(void);
/* executes code for Quantum */
void matrix_init_quantum(void);
void matrix_scan_quantum(void);
void matrix_init_kb(void);
void matrix_scan_kb(void);
void matrix_init_user(void);
void matrix_scan_user(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,34 @@
#pragma once
#include "quantum.h"
#include "config_led.h"
#include "matrix.h"
#include "i2c_master.h"
#include "led_matrix.h" //For led keycodes
#include "usb/udi_cdc.h"
#include "usb/usb2422.h"
#define LAYOUT( \
K01, K02, K03, K04, K05, K06, K07, K08, K09, K10, K11, K12, K13, K14, \
K15, K16, K17, K18, K19, K20, K21, K22, K23, K24, K25, K26, K27, K28, \
K29, K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K40, K41, K42, \
K43, K44, K45, K46, K47, K48, K49, K50, K51, K52, K53, K54, K55, K56, \
K57, K58, K59, K60, K61 \
) { \
{ K01, K02, K03, K04, K05, K06, K07, K08, K09, K10, K11, K12, K13, K14 }, \
{ K15, K16, K17, K18, K19, K20, K21, K22, K23, K24, K25, K26, K27, K28 }, \
{ K29, K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K40, KC_NO, K41 }, \
{ K42, KC_NO, K43, K44, K45, K46, K47, K48, K49, K50, K51, K52, KC_NO, K53 }, \
{ K54, K55, K56, KC_NO, KC_NO, KC_NO, K57, KC_NO, KC_NO, KC_NO, K58, K59, K60, K61 } \
}
#define TOGGLE_FLAG_AND_PRINT(var, name) { \
if (var) { \
dprintf(name " disabled\r\n"); \
var = !var; \
} else { \
var = !var; \
dprintf(name " enabled\r\n"); \
} \
}

View File

@@ -0,0 +1,38 @@
# project specific files
SRC = matrix.c
SRC += config_led.c
SRC += spi.c
SRC += usb.c
#For platform and packs
ARM_ATSAM = SAMD51J18A
MCU = cortex-m4
CUSTOM_MATRIX = yes
# Build Options
# comment out to disable the options.
#
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 = no # Console for debug(+400)
COMMAND_ENABLE = no # 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 = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality on B7 by default
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
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
HD44780_ENABLE = no # Enable support for HD44780 based LCDs (+400)
VIRTSER_ENABLE = no # USB Serial Driver
RAW_ENABLE = no # Raw device
AUTO_SHIFT_ENABLE = no # Auto Shift
# Custom RGB matrix handling
RGB_MATRIX_ENABLE = custom

View File

@@ -0,0 +1,60 @@
/*
Copyright 2019 Massdrop Inc.
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 "arm_atsam_protocol.h"
void SR_EXP_Init_kb(void) {
/* Initialize shift register */
SR_EXP_OE_N_DIS;
SR_EXP_RCLK_HI;
SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; //Data Order - LSB is transferred first
SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; //Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; //Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3; //Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; //Data Output PAD[0], Serial Clock PAD[1]
SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; //Operating Mode - Master operation
SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; //Enable - Peripheral is enabled or being enabled
while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { DBGC(DC_SPI_EXP_SYNC_ENABLING); }
/* Set default shift register values */
sr_exp_data.reg = 0; //Clear data register
sr_exp_data.bit.HUB_CONNECT = 0; //USB Hub disconnected
sr_exp_data.bit.HUB_RESET_N = 0; //USB Hub in reset state
sr_exp_data.bit.SRC_1_A5 = 1; //Set CON1 CC A5 as Rd 5.1k
sr_exp_data.bit.SRC_1_B5 = 1; //Set CON1 CC B5 as Rd 5.1k
sr_exp_data.bit.SRC_2_A5 = 1; //Set CON2 CC A5 as Rd 5.1k
sr_exp_data.bit.SRC_2_B5 = 1; //Set CON2 CC B5 as Rd 5.1k
sr_exp_data.bit.S_A_UP = 0; //0 = DN1 to A and UP to B, 1 = DN1 to B and UP to A
sr_exp_data.bit.S_A_EXT = 1; //0 = Onboard, 1 = Offboard
sr_exp_data.bit.S_B_EXT = 0; //1 = Onboard, 0 = Offboard
sr_exp_data.bit.ENB = 0; //Disable CON1
sr_exp_data.bit.ENA = 0; //Disable CON2
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
sr_exp_data.bit.IRST = 1; //LED drivers I2C in reset
sr_exp_data.bit.SDB_N = 0; //LED drivers in shutdown
/* Write shift register data */
SR_EXP_WriteData();
/* Enable shift register output */
SR_EXP_OE_N_ENA;
}

View File

@@ -0,0 +1,119 @@
/*
Copyright 2019 Massdrop Inc.
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 "arm_atsam_protocol.h"
void usb_set_host_kb(uint8_t con, uint8_t rp_best_index) {
if (con == 1) {
//DN1 to A (CON2/EX2), UP to B (CON1/EX1)
sr_exp_data.bit.S_A_UP = 1; //0 = DN1 to B and UP to A, 1 = DN1 to A and UP to B (SAI-SBI)
if (ADC_USBC_IS_ONB(rp_best_index)) { //Check if the port detected is onboard
sr_exp_data.bit.S_B_EXT = 1; //Onboard port
g_usb_host_port = USB_HOST_PORT_1; //Save host port
} else { //Port is external
sr_exp_data.bit.S_B_EXT = 0; //External port
g_usb_host_port = USB_HOST_PORT_1_EXT; //Save host port
}
sr_exp_data.bit.E_VBUS_1 = 1; //Enable CON1 5V
SR_EXP_WriteData(); //Update port configuration
} else if (con == 2) {
//DN1 to B (CON1/EX1), UP to A (CON2/EX2)
sr_exp_data.bit.S_A_UP = 0; //0 = DN1 to B and UP to A, 1 = DN1 to A and UP to B (SAI-SBI)
if (ADC_USBC_IS_ONB(rp_best_index)) { //Check if the port detected is onboard
sr_exp_data.bit.S_A_EXT = 0; //Onboard port
g_usb_host_port = USB_HOST_PORT_2; //Save host port
} else { //Port is external
sr_exp_data.bit.S_A_EXT = 1; //External port
g_usb_host_port = USB_HOST_PORT_2_EXT; //Save host port
}
sr_exp_data.bit.E_VBUS_2 = 1; //Enable CON2 5V
SR_EXP_WriteData(); //Update port configuration
}
}
void usb_set_extra_kb(uint8_t con) {
if (con == 1) {
sr_exp_data.bit.SRC_1_A5 = 0; //Set CON1 CC A5 as Rp 56k
sr_exp_data.bit.SRC_1_B5 = 0; //Set CON1 CC B5 as Rp 56k
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
SR_EXP_WriteData(); //Update port configuration
} else if (con == 2) {
sr_exp_data.bit.SRC_2_A5 = 0; //Set CON2 CC A5 as Rp 56k
sr_exp_data.bit.SRC_2_B5 = 0; //Set CON2 CC B5 as Rp 56k
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
SR_EXP_WriteData(); //Update port configuration
}
}
void usb_init_host_detection_kb(void) {
//Disable 5V
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
//Configure default paths
sr_exp_data.bit.S_A_UP = 0; //DN1 TO A & UP TO B WHEN 1, DN1 TO B & UP TO A WHEN 0
sr_exp_data.bit.S_A_EXT = 1; //0 = Onboard, 1 = Offboard (SAO)
sr_exp_data.bit.S_B_EXT = 0; //1 = Onboard, 0 = Offboard (SBO)
//Configure CC lines
sr_exp_data.bit.SRC_1_A5 = 1; //Set CON1 CC A5 as Rd 5.1k
sr_exp_data.bit.SRC_1_B5 = 1; //Set CON1 CC B5 as Rd 5.1k
sr_exp_data.bit.SRC_2_A5 = 1; //Set CON2 CC A5 as Rd 5.1k
sr_exp_data.bit.SRC_2_B5 = 1; //Set CON2 CC B5 as Rd 5.1k
//Enable ports
sr_exp_data.bit.ENB = 1; //Enable CON1/EX1 for use
sr_exp_data.bit.ENA = 1; //Enable CON2/EX2 for use
SR_EXP_WriteData(); //Update port configuration
}
//Return 1 if configuration successful
//Return 0 otherwise
uint8_t usb_attach_port_configure_kb(uint8_t g_usb_host_port, uint16_t usbc_cc_a5_v, uint16_t usbc_cc_b5_v) {
if (USB_HOST_IS_1(g_usb_host_port)) { //If host is port 1
//Set up port 2
if (USBC_IS_SINK_ONB(usbc_cc_a5_v, usbc_cc_b5_v)) { //If onboard port detected
sr_exp_data.bit.S_A_EXT = 0; //Set port 2 as onboard port
SR_EXP_WriteData(); //Update port configuration
return 1;
} else if (USBC_IS_SINK_EXT(usbc_cc_a5_v, usbc_cc_b5_v)) { //If external port detected
sr_exp_data.bit.S_A_EXT = 1; //Set port 2 as onboard port
SR_EXP_WriteData(); //Update port configuration
return 1;
}
} else if (USB_HOST_IS_2(g_usb_host_port)) { //If host is on port 2
//Set up port 1
if (USBC_IS_SINK_ONB(usbc_cc_a5_v, usbc_cc_b5_v)) { //If onboard port detected
sr_exp_data.bit.S_B_EXT = 1; //Set port 1 as onboard port
SR_EXP_WriteData(); //Update port configuration
return 1;
} else if (USBC_IS_SINK_EXT(usbc_cc_a5_v, usbc_cc_b5_v)) { //If external port detected
sr_exp_data.bit.S_B_EXT = 0; //Set port 1 as external port
SR_EXP_WriteData(); //Update port configuration
return 1;
}
}
return 0;
}

View File

@@ -0,0 +1,162 @@
/*
Copyright 2015 Jun Wako <wakojun@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 0x04D8
#define PRODUCT_ID 0xEE65
#define DEVICE_VER 0x0100
#define MANUFACTURER "Massdrop Inc."
#define PRODUCT "Massdrop SHIFT Keyboard"
#define SERIAL_NUM "Unavailable"
/* key matrix size */
#define MATRIX_ROWS 8
#define MATRIX_COLS 13
/* MCU Port name definitions */
#define PA 0
#define PB 1
/* Shift register IDs for key matrix */
/* SRBASE must be defined greater than MCU Port name definitions */
#define SRBASE 10
#define SRMAX (SRBASE + SERCOM_INST_NUM)
#define S4 (SRBASE + 4)
/* Macros to differentiate between MCU and Shift Register usage */
#define PORT_IS_MCU(x) (x < PORT_GROUPS)
#define PORT_IS_SR(x) (x >= SRBASE && x < SRMAX)
/* Port and Pin definition of key row hardware configuration */
#define MATRIX_ROW_PORTS PA, PA, PA, PA, PA, PA, PA, PA
#define MATRIX_ROW_PINS 0, 1, 2, 3, 4, 5, 6, 7
/* Port and Pin definition of key column hardware configuration */
#define MATRIX_COL_PORTS S4, S4, S4, S4, S4, S4, S4, S4, S4, S4, S4, S4, S4
#define MATRIX_COL_PINS 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
/* This Shift Register expands available hardware output lines to control additional peripherals */
/* It uses four lines from the MCU to provide 16 output lines */
/* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */
#define SR_EXP_RCLK_PORT PB
#define SR_EXP_RCLK_PIN 14
/* Shift Register Output Enable configuration (MCU to ShiftRegister.OE_N) */
#define SR_EXP_OE_N_PORT PB
#define SR_EXP_OE_N_PIN 15
/* SERCOM port to use for Shift Register SPI */
/* DATAOUT and SCLK must be configured to use hardware pins of this port */
#define SR_EXP_SERCOM_NUM 2
/* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */
#define SR_EXP_DATAOUT_PORT PA
#define SR_EXP_DATAOUT_PIN 12
#define SR_EXP_DATAOUT_MUX 2
/* Shift Register SPI Serial Clock configuration (MCU.SERCOMx.PAD[1] to ShiftRegister.SRCLK) */
#define SR_EXP_SCLK_PORT PA
#define SR_EXP_SCLK_PIN 13
#define SR_EXP_SCLK_MUX 2
/* This Shift Register is used as the Key Matrix Column Driver */
/* It uses four lines from the MCU to provide 16 output lines */
/* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */
#define SR_KC_RCLK_PORT PB
#define SR_KC_RCLK_PIN 6
/* Shift Register Output Enable configuration (MCU to ShiftRegister.OE_N) */
#define SR_KC_OE_N_PORT PB
#define SR_KC_OE_N_PIN 7
/* SERCOM port to use for Shift Register SPI */
/* DATAOUT and SCLK must be configured to use hardware pins of this port */
#define SR_KC_SERCOM_NUM 4
/* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */
#define SR_KC_DATAOUT_PORT PB
#define SR_KC_DATAOUT_PIN 8
#define SR_KC_DATAOUT_MUX 3
/* Shift Register SPI Serial Clock configuration (MCU.SERCOMx.PAD[1] to ShiftRegister.SRCLK) */
#define SR_KC_SCLK_PORT PB
#define SR_KC_SCLK_PIN 9
#define SR_KC_SCLK_MUX 3
/* Debug LED (Small LED Located near MCU) */
/* PCB M15 */
#define DEBUG_LED_ENABLE 1
#define DEBUG_LED_PORT PA
#define DEBUG_LED_PIN 27
/* Additional debugging ports */
/* PCB M44 */
#define DEBUG_PORT1_ENABLE 1
#define DEBUG_PORT1_PORT PB
#define DEBUG_PORT1_PIN 31
/* PCB M45 */
#define DEBUG_PORT2_ENABLE 1
#define DEBUG_PORT2_PORT PB
#define DEBUG_PORT2_PIN 10
/* PCB M46 */
#define DEBUG_PORT3_ENABLE 1
#define DEBUG_PORT3_PORT PB
#define DEBUG_PORT3_PIN 11
/* Debug Boot Tracing - During boot sequence, ground this pin to halt and display debug code using Debug LED */
/* This is useful in determining which hardware device may have malfunctioned or is improperly configured */
/* Feature is automatically disabled after successful boot */
/* PCB M27 */
#define DEBUG_BOOT_TRACING_ENABLE 1
#define DEBUG_BOOT_TRACING_PORT PB
#define DEBUG_BOOT_TRACING_PIN 23
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5
// Required BOOT key hold time (in ms) for restarting to bootloader -PS081419
#define BOOTKEY_HOLD_MS 2000
/* 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 boot in NKRO mode */
//#define FORCE_NKRO
/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/
/* disable debug print */
//#define NO_DEBUG
/* disable print */
//#define NO_PRINT
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION
#define RGB_MATRIX_KEYPRESSES
#define RGB_MATRIX_LED_PROCESS_LIMIT 15
#define RGB_MATRIX_LED_FLUSH_LIMIT 10
#define RGB_MATRIX_EXTRA_TOG
#include "config_led.h"

View File

@@ -0,0 +1,118 @@
/*
Copyright 2019 Massdrop Inc.
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
//ADC configuration table column indices
#define ADC_PORT 0
#define ADC_PIN 1
#define ADC_MUX 2
#define ADC_INDEX 3
#define ADC_MUXPOS 4
#define ADC_REFSEL 5
#define ADC_SAMPLENUM 6
#define ADC_SAMPLEN 7
//ADC configuration table row indices
#define ADC_5V 0 //5V bus voltage
#define ADC_C1A5 1 //Connector 1 A5 CC voltage
#define ADC_C1B5 2 //Connector 1 B5 CC voltage
#define ADC_C2A5 3 //Connector 2 A5 CC voltage
#define ADC_C2B5 4 //Connector 2 B5 CC voltage
#define ADC_C1I 5 //Connector 1 current
#define ADC_C2I 6 //Connector 2 current
//ADC_PORT: PORT of the PIN on the MCU (Ex: 0 = PA, 1 = PB, ...)
// Set ADC_PORT to ADC_NA if it is not available for use
//ADC_PIN: PIN on the MCU (Ex: 0 = 00, 1 = 01, 12 = 12, ...)
//ADC_MUX: PMUX setting for the MCU PIN (Ex: 0 = A, 1 = B, 2 = C, ...)
//ADC_INDEX: ADC to use (Ex: 0 = ADC0, 1 = ADC1, ...)
//ADC_MUXPOS: MUXPOS setting to read on the ADC (Use macros from Atmel library adc.h ADC_INPUTCTRL_MUXPOS_AIN*_Val)
//ADC_REFSEL: Reference the ADC is to use (Use macros from Atmel library adc.h ADC_REFCTRL_REFSEL_*_Val)
//ADC_SAMPLENUM: Number of samples to average for output (Use macros from Atmel library adc.h ADC_AVGCTRL_SAMPLENUM_*_Val)
//ADC_SAMPLEN: Sampling time for each sample in units of CLK_ADC cycles depending on the ADC clock frequency
// ADC_PORT ADC_MUX
// | ADC_PIN | ADC_INDEX
// | | | | ADC_MUXPOS ADC_REFSEL ADC_SAMPLENUM ADC_SAMPLEN
#define ADC_CONFIG_5V 1, 0, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN12_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 45
#define ADC_CONFIG_C1A5 1, 2, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN14_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 63
#define ADC_CONFIG_C1B5 1, 4, 1, 1, ADC_INPUTCTRL_MUXPOS_AIN6_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 63
#define ADC_CONFIG_C2A5 1, 1, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN13_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 63
#define ADC_CONFIG_C2B5 1, 5, 1, 1, ADC_INPUTCTRL_MUXPOS_AIN7_Val, ADC_REFCTRL_REFSEL_INTREF_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 63
#define ADC_CONFIG_C1I 0, 10, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN10_Val, ADC_REFCTRL_REFSEL_INTVCC1_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 45
#define ADC_CONFIG_C2I 0, 11, 1, 0, ADC_INPUTCTRL_MUXPOS_AIN11_Val, ADC_REFCTRL_REFSEL_INTVCC1_Val, ADC_AVGCTRL_SAMPLENUM_4_Val, 45
//Conversion values dependant upon the circuitry
#define ADC_I_MILLIAMPS_PER_COUNT -0.000980472f
#define ADC_I_MILLIAMPS_OFFSET 1.979711769f
#define ADC_5V_VOLTS_PER_COUNT 0.001904297f
#define ADC_5V_VOLTS_OFFSET 0.0f
#define ADC_5V_NOMINAL 5.0f
#define ADC_5V_NOMINAL_COUNTS (ADC_5V_NOMINAL / ADC_5V_VOLTS_PER_COUNT)
//Conversion macros
#define ADC_CI_C2I(macounts) ((float)macounts * ADC_I_MILLIAMPS_PER_COUNT + ADC_I_MILLIAMPS_OFFSET) //Converts connector current counts to milliamps
#define ADC_CI_I2C(ma) (uint16_t)((((float)ma - ADC_I_MILLIAMPS_OFFSET) / ADC_I_MILLIAMPS_PER_COUNT)) //Converts milliamps to connector current counts
#define ADC_5V_C2V(icounts) ((float)icounts * ADC_5V_VOLTS_PER_COUNT + ADC_5V_VOLTS_OFFSET) //Converts 5V Bus counts to volts
#define ADC_5V_V2C(v) (uint16_t)((((float)v - ADC_5V_VOLTS_OFFSET) / ADC_5V_VOLTS_PER_COUNT)) //Converts 5V Bus volts to counts
#define ADC_CC_5VCOR(v5counts, cc) ((float)v5counts == 0 ? 0 : (uint16_t)(ADC_5V_NOMINAL_COUNTS / (float)v5counts * (float)cc)) //Corrects CC counts to nominal 5V value
//Note: The extra port's onboard/external range is not reliable for onboard/external detection due to varying device implementations,
// so instead the extra port will follow the host port connection of onboard or external. We will still use
// a nominal value for device detection with a wider range though.
#define ADC_USBC_ONBOARD 951 //ADC value indicating the USB-C Connector is on main PCB
#define ADC_USBC_EXTERNAL 881 //ADC value indicating the USB-C Connector is on external PCB
#define ADC_USBC_RANGE ((ADC_USBC_ONBOARD - ADC_USBC_EXTERNAL) / 2) //Range of detection for extra port Rd
#define ADC_USBC_EXTRA_NOMINAL ((ADC_USBC_ONBOARD + ADC_USBC_EXTERNAL) / 2) //Nominal ADC value for detection of connected device
#define ADC_USBC_EXTRA_TOLERANCE (0.20f) //Tolerance for Rd
#define ADC_USBC_EXTRA_ADC_MAX ((float)ADC_USBC_EXTRA_NOMINAL + ((float)ADC_USBC_EXTRA_NOMINAL * ADC_USBC_EXTRA_TOLERANCE)) //Rd ADC max counts
#define ADC_USBC_EXTRA_ADC_MIN ((float)ADC_USBC_EXTRA_NOMINAL - ((float)ADC_USBC_EXTRA_NOMINAL * ADC_USBC_EXTRA_TOLERANCE)) //Rd ADC min counts
#define USBC_IS_SINK(a5, b5) ((a5 > ADC_USBC_EXTRA_ADC_MIN && a5 < ADC_USBC_EXTRA_ADC_MAX) || \
(b5 > ADC_USBC_EXTRA_ADC_MIN && b5 < ADC_USBC_EXTRA_ADC_MAX))
#define ADC_USBC_RP_DELTA_MAX 400 //Amount of noise to tolerate for Rp detection (this can be very generous as long as ranges do not overlap)
#define ADC_USBC_RP_TYPES 3 //56k, 22k, 10k
#define ADC_USBC_CON_TYPES 2 //Onboard, External
#define ADC_USBC_TYPES (ADC_USBC_RP_TYPES * ADC_USBC_CON_TYPES)
//These are the indices for ADC_USBC_RP_NOM
//xxK is a ADC_USBC_RP_TYPES
//ONB is for the onboard USB-C Connector and must have an even index number
//EXT is for the external USB-C Connector and must have an odd index number
#define ADC_USBC_56K_ONB 0
#define ADC_USBC_56K_EXT 1
#define ADC_USBC_22K_ONB 2
#define ADC_USBC_22K_EXT 3
#define ADC_USBC_10K_ONB 4
#define ADC_USBC_10K_EXT 5
#define ADC_USBC_IS_ONB(a) (a % 2 == 0) //Given a ADC_USBC_RP_NOM index, return true if the index refers to an onboard connector
#define ADC_USBC_IS_EXT(a) (a % 2 == 1) //Given a ADC_USBC_RP_NOM index, return true if the index refers to an external connector
//These values are for detecting whether or not the host is connected through the onboard USB or external USB
//The counts are calculated from a nominal 5V bus, then scaled depending on the measured 5V bus
//External connectors are detected through addition of a resistor to slightly drop readings while remaining within USB-C CC tolerances
//Set a value to -1 if it is not supported
//Source Rp 56k-Onb 56k-Ext 22k-Onb 22k-Ext 10k-Onb 10k-Ext
#define ADC_USBC_RP_NOM 999, 852, 2232, 1940, 3955, 3528
extern uint16_t adc_usbc_rp_nominal[ADC_USBC_TYPES];
#define POWER_CHECK_INTERVAL 1 //How often to check power usage for adjustment and safety (ms)
#define V_5V_AVGS 20 //Number of 5V readings to average for algorithms wanting stable readings rather than instantaneous

View File

@@ -0,0 +1,232 @@
#ifdef RGB_MATRIX_ENABLE
#include "shift.h"
#include "led_matrix.h"
#include "rgb_matrix.h"
#include "config_led.h"
// TODO: update after layout change
led_config_t g_led_config = {
{
{ 1, 2, 3, 5, 6, 7, 8, 10, 12, 14, 15, 16, 17 },
{ 22, 23, 4, 27, 29, 30, 9, 11, 13, 18, 19, 20, 21 },
{ 40, 24, 25, 28, 46, 31, 32, 34, 35, 36, 37, 38, 39 },
{ 58, 41, 26, 44, 47, 48, 33, 51, 52, 54, 55, 56, 57 },
{ 75, 42, 43, 45, 64, 49, 50, 68, 53, 71, 72, 73, 74 },
{ 92, 59, 61, 62, 65, 66, 67, 84, 69, 87, 88, 89, 91 },
{ 93, 60, 77, 63, 80, 82, 83, 85, 70, 90, 102, 98, 99 },
{ 94, 76, 78, 79, 95, 81, 96, 97, 86, 100, 101, NO_LED, NO_LED }
},
{
{ 6, 5 },
{ 29, 5 },
{ 41, 5 },
{ 52, 5 },
{ 63, 5 },
{ 81, 5 },
{ 92, 5 },
{ 103, 5 },
{ 115, 5 },
{ 132, 5 },
{ 143, 5 },
{ 155, 5 },
{ 166, 5 },
{ 183, 5 },
{ 195, 5 },
{ 206, 5 },
{ 218, 5 },
{ 183, 13 },
{ 195, 13 },
{ 206, 13 },
{ 218, 13 },
{ 6, 22 },
{ 18, 22 },
{ 29, 22 },
{ 41, 22 },
{ 52, 22 },
{ 63, 22 },
{ 75, 22 },
{ 86, 22 },
{ 98, 22 },
{ 109, 22 },
{ 121, 22 },
{ 132, 22 },
{ 143, 22 },
{ 161, 22 },
{ 183, 22 },
{ 195, 22 },
{ 206, 22 },
{ 218, 22 },
{ 9, 31 },
{ 23, 31 },
{ 35, 31 },
{ 46, 31 },
{ 58, 31 },
{ 69, 31 },
{ 81, 31 },
{ 92, 31 },
{ 103, 31 },
{ 115, 31 },
{ 126, 31 },
{ 138, 31 },
{ 149, 31 },
{ 163, 31 },
{ 183, 31 },
{ 195, 31 },
{ 206, 31 },
{ 218, 31 },
{ 11, 40 },
{ 26, 40 },
{ 38, 40 },
{ 49, 40 },
{ 61, 40 },
{ 72, 40 },
{ 83, 40 },
{ 95, 40 },
{ 106, 40 },
{ 118, 40 },
{ 129, 40 },
{ 141, 40 },
{ 159, 40 },
{ 183, 40 },
{ 195, 40 },
{ 206, 40 },
{ 218, 40 },
{ 13, 48 },
{ 32, 48 },
{ 43, 48 },
{ 55, 48 },
{ 66, 48 },
{ 78, 48 },
{ 89, 48 },
{ 101, 48 },
{ 112, 48 },
{ 123, 48 },
{ 135, 48 },
{ 151, 48 },
{ 183, 48 },
{ 195, 48 },
{ 206, 48 },
{ 169, 51 }, // up
{ 218, 53 }, // numpad enter
{ 8, 57 },
{ 22, 57 },
{ 36, 57 },
{ 79, 57 },
{ 123, 57 },
{ 141, 57 },
{ 195, 57 },
{ 206, 57 },
{ 158, 59 },
{ 169, 59 },
{ 181, 59 },
{ 2, 1 },
{ 12, 0 },
{ 32, 0 },
{ 42, 0 },
{ 52, 0 },
{ 62, 0 },
{ 72, 0 },
{ 82, 0 },
{ 92, 0 },
{ 102, 0 },
{ 112, 0 },
{ 122, 0 },
{ 132, 0 },
{ 142, 0 },
{ 152, 0 },
{ 162, 0 },
{ 172, 0 },
{ 182, 0 },
{ 192, 0 },
{ 212, 0 },
{ 222, 1 },
{ 224, 9 },
{ 224, 17 },
{ 224, 24 },
{ 224, 32 },
{ 224, 40 },
{ 224, 47 },
{ 224, 55 },
{ 222, 63 },
{ 212, 64 },
{ 202, 64 },
{ 192, 64 },
{ 182, 64 },
{ 172, 64 },
{ 162, 64 },
{ 152, 64 },
{ 142, 64 },
{ 132, 64 },
{ 122, 64 },
{ 112, 64 },
{ 102, 64 },
{ 92, 64 },
{ 82, 64 },
{ 72, 64 },
{ 62, 64 },
{ 52, 64 },
{ 42, 64 },
{ 32, 64 },
{ 22, 64 },
{ 12, 64 },
{ 2, 63 },
{ 0, 55 },
{ 0, 47 },
{ 0, 40 },
{ 0, 32 },
{ 0, 24 },
{ 0, 17 },
{ 0, 9 }
},
{
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4,
4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
4, 4, 4, 4,
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4,
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
4, 4, 4, 4,
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
4, 4, 4,
4, // up
4, // numpad enter
1, 1, 1, 4, 1, 1, 4, 4,
4, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2
}
};
#ifdef USB_LED_INDICATOR_ENABLE
void rgb_matrix_indicators_kb(void)
{
led_matrix_indicators();
}
#endif // USB_LED_INDICATOR_ENABLE
#endif

View File

@@ -0,0 +1,233 @@
/*
Copyright 2019 Massdrop Inc.
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
//Define number of IS31FL3733 drivers being used (1...16)
#define ISSI3733_DRIVER_COUNT 3
#define DRIVER_LED_TOTAL ISSI3733_LED_COUNT
//Hardware address of each driver (Refer to IS31FL3733 pdf "Table 1 Slave Address" and keyboard schematic)
#define ISSI3773_DRIVER_ADDRESSES { 0xA0, 0xBE, 0xA6 }
//LED I2C bus speed
#define I2C_HZ 870000
//Count of LED bodies
#define ISSI3733_LED_COUNT 160
#define LED_GCR_MAX 165 //Max GCR value (0 - 255) WARNING: Raising this value may overload the LED drivers and USB bus
#define LED_GCR_STEP 10 //GCR increment/decrement value
#ifdef USE_MASSDROP_CONFIGURATOR
#define ANIMATION_SPEED_STEP 1
#define BREATHE_STEP 1
#define BREATHE_MIN_STEP 0
#define BREATHE_MAX_STEP 255
#endif
//Default Global Current Register value (Default brightness 0 - 255)
#define ISSI3733_GCR_DEFAULT LED_GCR_MAX
//Automatic power rollback and recovery
#define V5_HIGH 2494 //5V high level (After low power detect, point at which LEDs are allowed to use more power )
#define V5_LOW 2434 //5V low level (LED power rolled back to stay above this limit)
#define V5_CAT 2206 //5V catastrophic level (Host USB port potential to shut down)
//LED Mapping - More practically generated from a spreadsheet program
//id: ID of the LED (Sync with PCB callouts)
//x: Physical X coordinate of LED (units do not matter)
//y: Physical Y coordinate of LED (units do not matter)
//drv: 1-Based index of ISSI3773_DRIVER_ADDRESSES
//cs: Matrix wiring CS col (1-16)
//swr: Matrix wiring SW Red row (1-12)
//swg: Matrix wiring SW Green row (1-12)
//swb: Matrix wiring SW Blue row (1-12)
//scan: Associated key matrix scancode (set 255 if none or 254 for LED to turn off in alternating mode)
//Note: Origin 0,0 may be located anywhere as the software will do the final layout
#define ISSI3733_LED_MAP { \
{ .id = 1, .x = 0.474, .y = 5.162, .adr = { .drv = 1, .cs = 1, .swr = 11, .swg = 10, .swb = 12 }, .scan = 0 }, \
{ .id = 2, .x = 1.974, .y = 5.162, .adr = { .drv = 1, .cs = 2, .swr = 11, .swg = 10, .swb = 12 }, .scan = 1 }, \
{ .id = 3, .x = 2.724, .y = 5.162, .adr = { .drv = 1, .cs = 3, .swr = 11, .swg = 10, .swb = 12 }, .scan = 2 }, \
{ .id = 4, .x = 3.474, .y = 5.162, .adr = { .drv = 1, .cs = 4, .swr = 11, .swg = 10, .swb = 12 }, .scan = 18 }, \
{ .id = 5, .x = 4.224, .y = 5.162, .adr = { .drv = 1, .cs = 5, .swr = 11, .swg = 10, .swb = 12 }, .scan = 3 }, \
{ .id = 6, .x = 5.349, .y = 5.162, .adr = { .drv = 1, .cs = 7, .swr = 11, .swg = 10, .swb = 12 }, .scan = 4 }, \
{ .id = 7, .x = 6.099, .y = 5.162, .adr = { .drv = 1, .cs = 8, .swr = 11, .swg = 10, .swb = 12 }, .scan = 5 }, \
{ .id = 8, .x = 6.849, .y = 5.162, .adr = { .drv = 1, .cs = 9, .swr = 11, .swg = 10, .swb = 12 }, .scan = 6 }, \
{ .id = 9, .x = 7.599, .y = 5.162, .adr = { .drv = 1, .cs = 10, .swr = 11, .swg = 10, .swb = 12 }, .scan = 22 }, \
{ .id = 10, .x = 8.724, .y = 5.162, .adr = { .drv = 2, .cs = 1, .swr = 11, .swg = 10, .swb = 12 }, .scan = 7 }, \
{ .id = 11, .x = 9.474, .y = 5.162, .adr = { .drv = 2, .cs = 2, .swr = 11, .swg = 10, .swb = 12 }, .scan = 23 }, \
{ .id = 12, .x = 10.224, .y = 5.162, .adr = { .drv = 2, .cs = 3, .swr = 11, .swg = 10, .swb = 12 }, .scan = 8 }, \
{ .id = 13, .x = 10.974, .y = 5.162, .adr = { .drv = 2, .cs = 4, .swr = 11, .swg = 10, .swb = 12 }, .scan = 24 }, \
{ .id = 14, .x = 12.099, .y = 5.162, .adr = { .drv = 2, .cs = 5, .swr = 11, .swg = 10, .swb = 12 }, .scan = 9 }, \
{ .id = 15, .x = 12.849, .y = 5.162, .adr = { .drv = 2, .cs = 6, .swr = 11, .swg = 10, .swb = 12 }, .scan = 10 }, \
{ .id = 16, .x = 13.599, .y = 5.162, .adr = { .drv = 2, .cs = 7, .swr = 11, .swg = 10, .swb = 12 }, .scan = 11 }, \
{ .id = 17, .x = 14.349, .y = 5.162, .adr = { .drv = 2, .cs = 8, .swr = 11, .swg = 10, .swb = 12 }, .scan = 12 }, \
{ .id = 18, .x = 12.099, .y = 4.412, .adr = { .drv = 2, .cs = 5, .swr = 8, .swg = 7, .swb = 9 }, .scan = 25 }, \
{ .id = 19, .x = 12.849, .y = 4.412, .adr = { .drv = 2, .cs = 6, .swr = 8, .swg = 7, .swb = 9 }, .scan = 26 }, \
{ .id = 20, .x = 13.599, .y = 4.412, .adr = { .drv = 2, .cs = 7, .swr = 8, .swg = 7, .swb = 9 }, .scan = 27 }, \
{ .id = 21, .x = 14.349, .y = 4.412, .adr = { .drv = 2, .cs = 8, .swr = 8, .swg = 7, .swb = 9 }, .scan = 28 }, \
{ .id = 22, .x = 0.474, .y = 3.662, .adr = { .drv = 1, .cs = 1, .swr = 8, .swg = 7, .swb = 9 }, .scan = 16 }, \
{ .id = 23, .x = 1.224, .y = 3.662, .adr = { .drv = 1, .cs = 11, .swr = 8, .swg = 7, .swb = 9 }, .scan = 17 }, \
{ .id = 24, .x = 1.974, .y = 3.662, .adr = { .drv = 1, .cs = 2, .swr = 8, .swg = 7, .swb = 9 }, .scan = 33 }, \
{ .id = 25, .x = 2.724, .y = 3.662, .adr = { .drv = 1, .cs = 3, .swr = 8, .swg = 7, .swb = 9 }, .scan = 34 }, \
{ .id = 26, .x = 3.474, .y = 3.662, .adr = { .drv = 1, .cs = 4, .swr = 8, .swg = 7, .swb = 9 }, .scan = 50 }, \
{ .id = 27, .x = 4.224, .y = 3.662, .adr = { .drv = 1, .cs = 5, .swr = 8, .swg = 7, .swb = 9 }, .scan = 19 }, \
{ .id = 28, .x = 4.974, .y = 3.662, .adr = { .drv = 1, .cs = 6, .swr = 8, .swg = 7, .swb = 9 }, .scan = 35 }, \
{ .id = 29, .x = 5.724, .y = 3.662, .adr = { .drv = 1, .cs = 7, .swr = 8, .swg = 7, .swb = 9 }, .scan = 20 }, \
{ .id = 30, .x = 6.474, .y = 3.662, .adr = { .drv = 1, .cs = 8, .swr = 8, .swg = 7, .swb = 9 }, .scan = 21 }, \
{ .id = 31, .x = 7.224, .y = 3.662, .adr = { .drv = 1, .cs = 9, .swr = 8, .swg = 7, .swb = 9 }, .scan = 37 }, \
{ .id = 32, .x = 7.974, .y = 3.662, .adr = { .drv = 1, .cs = 10, .swr = 8, .swg = 7, .swb = 9 }, .scan = 38 }, \
{ .id = 33, .x = 8.724, .y = 3.662, .adr = { .drv = 2, .cs = 1, .swr = 5, .swg = 4, .swb = 6 }, .scan = 54 }, \
{ .id = 34, .x = 9.474, .y = 3.662, .adr = { .drv = 2, .cs = 2, .swr = 5, .swg = 4, .swb = 6 }, .scan = 39 }, \
{ .id = 35, .x = 10.599, .y = 3.662, .adr = { .drv = 2, .cs = 4, .swr = 5, .swg = 4, .swb = 6 }, .scan = 40 }, \
{ .id = 36, .x = 12.099, .y = 3.662, .adr = { .drv = 2, .cs = 5, .swr = 5, .swg = 4, .swb = 6 }, .scan = 41 }, \
{ .id = 37, .x = 12.849, .y = 3.662, .adr = { .drv = 2, .cs = 6, .swr = 5, .swg = 4, .swb = 6 }, .scan = 42 }, \
{ .id = 38, .x = 13.599, .y = 3.662, .adr = { .drv = 2, .cs = 7, .swr = 5, .swg = 4, .swb = 6 }, .scan = 43 }, \
{ .id = 39, .x = 14.349, .y = 3.662, .adr = { .drv = 2, .cs = 8, .swr = 5, .swg = 4, .swb = 6 }, .scan = 44 }, \
{ .id = 40, .x = 0.662, .y = 2.912, .adr = { .drv = 1, .cs = 1, .swr = 5, .swg = 4, .swb = 6 }, .scan = 32 }, \
{ .id = 41, .x = 1.599, .y = 2.912, .adr = { .drv = 1, .cs = 2, .swr = 5, .swg = 4, .swb = 6 }, .scan = 49 }, \
{ .id = 42, .x = 2.349, .y = 2.912, .adr = { .drv = 1, .cs = 3, .swr = 5, .swg = 4, .swb = 6 }, .scan = 65 }, \
{ .id = 43, .x = 3.099, .y = 2.912, .adr = { .drv = 1, .cs = 4, .swr = 5, .swg = 4, .swb = 6 }, .scan = 66 }, \
{ .id = 44, .x = 3.849, .y = 2.912, .adr = { .drv = 1, .cs = 5, .swr = 5, .swg = 4, .swb = 6 }, .scan = 51 }, \
{ .id = 45, .x = 4.599, .y = 2.912, .adr = { .drv = 1, .cs = 6, .swr = 5, .swg = 4, .swb = 6 }, .scan = 67 }, \
{ .id = 46, .x = 5.349, .y = 2.912, .adr = { .drv = 1, .cs = 7, .swr = 5, .swg = 4, .swb = 6 }, .scan = 36 }, \
{ .id = 47, .x = 6.099, .y = 2.912, .adr = { .drv = 1, .cs = 8, .swr = 5, .swg = 4, .swb = 6 }, .scan = 52 }, \
{ .id = 48, .x = 6.849, .y = 2.912, .adr = { .drv = 1, .cs = 9, .swr = 5, .swg = 4, .swb = 6 }, .scan = 53 }, \
{ .id = 49, .x = 7.599, .y = 2.912, .adr = { .drv = 1, .cs = 10, .swr = 5, .swg = 4, .swb = 6 }, .scan = 69 }, \
{ .id = 50, .x = 8.349, .y = 2.912, .adr = { .drv = 2, .cs = 1, .swr = 2, .swg = 1, .swb = 3 }, .scan = 70 }, \
{ .id = 51, .x = 9.099, .y = 2.912, .adr = { .drv = 2, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 55 }, \
{ .id = 52, .x = 9.849, .y = 2.912, .adr = { .drv = 2, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 56 }, \
{ .id = 53, .x = 10.787, .y = 2.912, .adr = { .drv = 2, .cs = 4, .swr = 2, .swg = 1, .swb = 3 }, .scan = 72 }, \
{ .id = 54, .x = 12.099, .y = 2.912, .adr = { .drv = 2, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 57 }, \
{ .id = 55, .x = 12.849, .y = 2.912, .adr = { .drv = 2, .cs = 6, .swr = 2, .swg = 1, .swb = 3 }, .scan = 58 }, \
{ .id = 56, .x = 13.599, .y = 2.912, .adr = { .drv = 2, .cs = 7, .swr = 2, .swg = 1, .swb = 3 }, .scan = 59 }, \
{ .id = 57, .x = 14.349, .y = 2.912, .adr = { .drv = 2, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 60 }, \
{ .id = 58, .x = 0.756, .y = 2.162, .adr = { .drv = 1, .cs = 1, .swr = 2, .swg = 1, .swb = 3 }, .scan = 48 }, \
{ .id = 59, .x = 1.787, .y = 2.162, .adr = { .drv = 1, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 81 }, \
{ .id = 60, .x = 2.537, .y = 2.162, .adr = { .drv = 1, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 97 }, \
{ .id = 61, .x = 3.287, .y = 2.162, .adr = { .drv = 1, .cs = 4, .swr = 2, .swg = 1, .swb = 3 }, .scan = 82 }, \
{ .id = 62, .x = 4.037, .y = 2.162, .adr = { .drv = 1, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 83 }, \
{ .id = 63, .x = 4.787, .y = 2.162, .adr = { .drv = 1, .cs = 6, .swr = 2, .swg = 1, .swb = 3 }, .scan = 99 }, \
{ .id = 64, .x = 5.537, .y = 2.162, .adr = { .drv = 1, .cs = 7, .swr = 2, .swg = 1, .swb = 3 }, .scan = 68 }, \
{ .id = 65, .x = 6.287, .y = 2.162, .adr = { .drv = 1, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 84 }, \
{ .id = 66, .x = 7.037, .y = 2.162, .adr = { .drv = 1, .cs = 9, .swr = 2, .swg = 1, .swb = 3 }, .scan = 85 }, \
{ .id = 67, .x = 7.787, .y = 2.162, .adr = { .drv = 1, .cs = 10, .swr = 2, .swg = 1, .swb = 3 }, .scan = 86 }, \
{ .id = 68, .x = 8.537, .y = 2.162, .adr = { .drv = 2, .cs = 9, .swr = 2, .swg = 1, .swb = 3 }, .scan = 71 }, \
{ .id = 69, .x = 9.287, .y = 2.162, .adr = { .drv = 2, .cs = 10, .swr = 2, .swg = 1, .swb = 3 }, .scan = 88 }, \
{ .id = 70, .x = 10.506, .y = 2.162, .adr = { .drv = 2, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 104 }, \
{ .id = 71, .x = 12.099, .y = 2.162, .adr = { .drv = 2, .cs = 13, .swr = 2, .swg = 1, .swb = 3 }, .scan = 73 }, \
{ .id = 72, .x = 12.849, .y = 2.162, .adr = { .drv = 2, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 74 }, \
{ .id = 73, .x = 13.599, .y = 2.162, .adr = { .drv = 2, .cs = 15, .swr = 2, .swg = 1, .swb = 3 }, .scan = 75 }, \
{ .id = 74, .x = 14.349, .y = 2.162, .adr = { .drv = 2, .cs = 16, .swr = 2, .swg = 1, .swb = 3 }, .scan = 76 }, \
{ .id = 75, .x = 0.943, .y = 1.412, .adr = { .drv = 1, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 64 }, \
{ .id = 76, .x = 2.162, .y = 1.412, .adr = { .drv = 1, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 113 }, \
{ .id = 77, .x = 2.912, .y = 1.412, .adr = { .drv = 1, .cs = 13, .swr = 2, .swg = 1, .swb = 3 }, .scan = 98 }, \
{ .id = 78, .x = 3.662, .y = 1.412, .adr = { .drv = 1, .cs = 13, .swr = 8, .swg = 7, .swb = 9 }, .scan = 114 }, \
{ .id = 79, .x = 4.412, .y = 1.412, .adr = { .drv = 1, .cs = 14, .swr = 8, .swg = 7, .swb = 9 }, .scan = 115 }, \
{ .id = 80, .x = 5.162, .y = 1.412, .adr = { .drv = 1, .cs = 14, .swr = 2, .swg = 1, .swb = 3 }, .scan = 100 }, \
{ .id = 81, .x = 5.912, .y = 1.412, .adr = { .drv = 1, .cs = 15, .swr = 5, .swg = 4, .swb = 6 }, .scan = 117 }, \
{ .id = 82, .x = 6.662, .y = 1.412, .adr = { .drv = 1, .cs = 15, .swr = 2, .swg = 1, .swb = 3 }, .scan = 101 }, \
{ .id = 83, .x = 7.414, .y = 1.41, .adr = { .drv = 1, .cs = 16, .swr = 2, .swg = 1, .swb = 3 }, .scan = 102 }, \
{ .id = 84, .x = 8.162, .y = 1.412, .adr = { .drv = 2, .cs = 9, .swr = 5, .swg = 4, .swb = 6 }, .scan = 87 }, \
{ .id = 85, .x = 8.912, .y = 1.412, .adr = { .drv = 2, .cs = 10, .swr = 5, .swg = 4, .swb = 6 }, .scan = 103 }, \
{ .id = 86, .x = 9.943, .y = 1.412, .adr = { .drv = 2, .cs = 11, .swr = 5, .swg = 4, .swb = 6 }, .scan = 120 }, \
{ .id = 87, .x = 12.099, .y = 1.412, .adr = { .drv = 2, .cs = 13, .swr = 5, .swg = 4, .swb = 6 }, .scan = 89 }, \
{ .id = 88, .x = 12.849, .y = 1.412, .adr = { .drv = 2, .cs = 14, .swr = 5, .swg = 4, .swb = 6 }, .scan = 90 }, \
{ .id = 89, .x = 13.599, .y = 1.412, .adr = { .drv = 2, .cs = 15, .swr = 5, .swg = 4, .swb = 6 }, .scan = 91 }, \
{ .id = 90, .x = 11.162, .y = 1.224, .adr = { .drv = 2, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 105 }, \
{ .id = 91, .x = 14.349, .y = 1.037, .adr = { .drv = 2, .cs = 16, .swr = 8, .swg = 7, .swb = 9 }, .scan = 92 }, \
{ .id = 92, .x = 0.568, .y = 0.662, .adr = { .drv = 1, .cs = 11, .swr = 5, .swg = 4, .swb = 6 }, .scan = 80 }, \
{ .id = 93, .x = 1.506, .y = 0.662, .adr = { .drv = 1, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 96 }, \
{ .id = 94, .x = 2.443, .y = 0.662, .adr = { .drv = 1, .cs = 13, .swr = 5, .swg = 4, .swb = 6 }, .scan = 112 }, \
{ .id = 95, .x = 5.256, .y = 0.662, .adr = { .drv = 1, .cs = 14, .swr = 5, .swg = 4, .swb = 6 }, .scan = 116 }, \
{ .id = 96, .x = 8.162, .y = 0.662, .adr = { .drv = 2, .cs = 9, .swr = 8, .swg = 7, .swb = 9 }, .scan = 118 }, \
{ .id = 97, .x = 9.287, .y = 0.662, .adr = { .drv = 2, .cs = 10, .swr = 8, .swg = 7, .swb = 9 }, .scan = 119 }, \
{ .id = 98, .x = 12.849, .y = 0.662, .adr = { .drv = 2, .cs = 14, .swr = 8, .swg = 7, .swb = 9 }, .scan = 107 }, \
{ .id = 99, .x = 13.599, .y = 0.662, .adr = { .drv = 2, .cs = 15, .swr = 8, .swg = 7, .swb = 9 }, .scan = 108 }, \
{ .id = 100, .x = 10.412, .y = 0.474, .adr = { .drv = 2, .cs = 11, .swr = 8, .swg = 7, .swb = 9 }, .scan = 121 }, \
{ .id = 101, .x = 11.162, .y = 0.474, .adr = { .drv = 2, .cs = 12, .swr = 8, .swg = 7, .swb = 9 }, .scan = 122 }, \
{ .id = 102, .x = 11.912, .y = 0.474, .adr = { .drv = 2, .cs = 13, .swr = 8, .swg = 7, .swb = 9 }, .scan = 106 }, \
{ .id = 103, .x = 0.168, .y = 5.468, .adr = { .drv = 3, .cs = 1, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 104, .x = 0.827, .y = 5.571, .adr = { .drv = 3, .cs = 1, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 105, .x = 2.144, .y = 5.571, .adr = { .drv = 3, .cs = 2, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 106, .x = 2.802, .y = 5.571, .adr = { .drv = 3, .cs = 3, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 107, .x = 3.461, .y = 5.571, .adr = { .drv = 3, .cs = 3, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 108, .x = 4.119, .y = 5.571, .adr = { .drv = 3, .cs = 4, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 109, .x = 4.778, .y = 5.571, .adr = { .drv = 3, .cs = 4, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 110, .x = 5.436, .y = 5.571, .adr = { .drv = 3, .cs = 5, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 111, .x = 6.095, .y = 5.571, .adr = { .drv = 3, .cs = 5, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 112, .x = 6.753, .y = 5.571, .adr = { .drv = 3, .cs = 6, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 113, .x = 7.412, .y = 5.571, .adr = { .drv = 3, .cs = 6, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 114, .x = 8.07, .y = 5.571, .adr = { .drv = 3, .cs = 7, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 115, .x = 8.729, .y = 5.571, .adr = { .drv = 3, .cs = 7, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 116, .x = 9.387, .y = 5.571, .adr = { .drv = 3, .cs = 8, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 117, .x = 10.046, .y = 5.571, .adr = { .drv = 3, .cs = 8, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 118, .x = 10.704, .y = 5.571, .adr = { .drv = 3, .cs = 9, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 119, .x = 11.363, .y = 5.571, .adr = { .drv = 3, .cs = 9, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 120, .x = 12.021, .y = 5.571, .adr = { .drv = 3, .cs = 10, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 121, .x = 12.68, .y = 5.571, .adr = { .drv = 3, .cs = 10, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 122, .x = 13.997, .y = 5.571, .adr = { .drv = 3, .cs = 11, .swr = 5, .swg = 4, .swb = 6 }, .scan = 254 }, \
{ .id = 123, .x = 14.656, .y = 5.468, .adr = { .drv = 3, .cs = 11, .swr = 2, .swg = 1, .swb = 3 }, .scan = 255 }, \
{ .id = 124, .x = 14.759, .y = 4.806, .adr = { .drv = 3, .cs = 12, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 125, .x = 14.759, .y = 4.143, .adr = { .drv = 3, .cs = 12, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 126, .x = 14.759, .y = 3.481, .adr = { .drv = 3, .cs = 12, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 127, .x = 14.759, .y = 2.818, .adr = { .drv = 3, .cs = 13, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 128, .x = 14.759, .y = 2.156, .adr = { .drv = 3, .cs = 13, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 129, .x = 14.759, .y = 1.493, .adr = { .drv = 3, .cs = 13, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 130, .x = 14.759, .y = 0.831, .adr = { .drv = 3, .cs = 14, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 131, .x = 14.656, .y = 0.168, .adr = { .drv = 3, .cs = 14, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 132, .x = 13.997, .y = 0.065, .adr = { .drv = 3, .cs = 11, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 133, .x = 13.338, .y = 0.065, .adr = { .drv = 3, .cs = 11, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 134, .x = 12.68, .y = 0.065, .adr = { .drv = 3, .cs = 10, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 135, .x = 12.021, .y = 0.065, .adr = { .drv = 3, .cs = 10, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 136, .x = 11.363, .y = 0.065, .adr = { .drv = 3, .cs = 9, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 137, .x = 10.704, .y = 0.065, .adr = { .drv = 3, .cs = 9, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 138, .x = 10.046, .y = 0.065, .adr = { .drv = 3, .cs = 8, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 139, .x = 9.387, .y = 0.065, .adr = { .drv = 3, .cs = 8, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 140, .x = 8.729, .y = 0.065, .adr = { .drv = 3, .cs = 7, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 141, .x = 8.07, .y = 0.065, .adr = { .drv = 3, .cs = 7, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 142, .x = 7.412, .y = 0.065, .adr = { .drv = 3, .cs = 6, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 143, .x = 6.753, .y = 0.065, .adr = { .drv = 3, .cs = 6, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 144, .x = 6.095, .y = 0.065, .adr = { .drv = 3, .cs = 5, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 145, .x = 5.436, .y = 0.065, .adr = { .drv = 3, .cs = 5, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 146, .x = 4.778, .y = 0.065, .adr = { .drv = 3, .cs = 4, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 147, .x = 4.119, .y = 0.065, .adr = { .drv = 3, .cs = 4, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 148, .x = 3.461, .y = 0.065, .adr = { .drv = 3, .cs = 3, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 149, .x = 2.802, .y = 0.065, .adr = { .drv = 3, .cs = 3, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 150, .x = 2.144, .y = 0.065, .adr = { .drv = 3, .cs = 2, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 151, .x = 1.485, .y = 0.065, .adr = { .drv = 3, .cs = 2, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 152, .x = 0.827, .y = 0.065, .adr = { .drv = 3, .cs = 1, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 153, .x = 0.168, .y = 0.168, .adr = { .drv = 3, .cs = 1, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 154, .x = 0.065, .y = 0.831, .adr = { .drv = 3, .cs = 15, .swr = 8, .swg = 7, .swb = 9 }, .scan = 254 }, \
{ .id = 155, .x = 0.065, .y = 1.493, .adr = { .drv = 3, .cs = 15, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 156, .x = 0.065, .y = 2.156, .adr = { .drv = 3, .cs = 15, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 }, \
{ .id = 157, .x = 0.065, .y = 2.818, .adr = { .drv = 3, .cs = 15, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 158, .x = 0.065, .y = 3.481, .adr = { .drv = 3, .cs = 16, .swr = 11, .swg = 10, .swb = 12 }, .scan = 254 }, \
{ .id = 159, .x = 0.065, .y = 4.143, .adr = { .drv = 3, .cs = 16, .swr = 5, .swg = 4, .swb = 6 }, .scan = 255 }, \
{ .id = 160, .x = 0.065, .y = 4.806, .adr = { .drv = 3, .cs = 16, .swr = 2, .swg = 1, .swb = 3 }, .scan = 254 } \
};
#define USB_LED_INDICATOR_ENABLE //Comment out to disable indicator functionality
#ifdef USB_LED_INDICATOR_ENABLE //Scan codes refer to actual key matrix codes, not KC_* (255 to disable)
#define USB_LED_NUM_LOCK_SCANCODE 41
#define USB_LED_CAPS_LOCK_SCANCODE 48
#define USB_LED_SCROLL_LOCK_SCANCODE 28
#define USB_LED_COMPOSE_SCANCODE 255
#define USB_LED_KANA_SCANCODE 255
#endif //USB_LED_INDICATOR_ENABLE

View File

@@ -0,0 +1,42 @@
/*
Copyright 2019 Massdrop Inc.
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
/* Data structure to define Shift Register output expander hardware */
/* This structure gets shifted into registers LSB first */
typedef union {
struct {
uint16_t RSVD4:1; /*!< bit: 0 */
uint16_t SRC_2_B5:1; /*!< bit: 1 USBC-2 CC B5 UFP Rd 5.1k WHEN 1, DFP Rp 56k WHEN 0 */
uint16_t SRC_1_B5:1; /*!< bit: 2 USBC-1 CC B5 UFP Rd 5.1k WHEN 1, DFP Rp 56k WHEN 0 */
uint16_t S_B_EXT:1; /*!< bit: 3 B TO EX-1 WHEN 1, B TO USBC-1 WHEN 0 */
uint16_t SDB_N:1; /*!< bit: 4 SHUTDOWN IS31FL3733 CHIPS WHEN 0, RUN WHEN 1 */
uint16_t IRST:1; /*!< bit: 5 RESET IS31FL3733 I2C WHEN 1, RUN WHEN 0 */
uint16_t SRC_2_A5:1; /*!< bit: 6 USBC-2 CC A5 UFP Rd 5.1k WHEN 1, DFP Rp 56k WHEN 0 */
uint16_t SRC_1_A5:1; /*!< bit: 7 USBC-1 CC A5 UFP Rd 5.1k WHEN 1, DFP Rp 56k WHEN 0 */
uint16_t E_VBUS_2:1; /*!< bit: 8 ENABLE 5V TO USBC-2/EX-2 WHEN 1, DISABLE WHEN 0 */
uint16_t E_VBUS_1:1; /*!< bit: 9 ENABLE 5V TO USBC-1/EX-1 WHEN 1, DISABLE WHEN 0 */
uint16_t ENB:1; /*!< bit: 10 ENABLE CHANNEL B USBC-1/EX-1 WHEN 1, DISABLE WHEN 0 */
uint16_t S_A_EXT:1; /*!< bit: 11 A TO USBC-2 WHEN 1, A TO EX-2 WHEN 0 */
uint16_t ENA:1; /*!< bit: 12 ENABLE CHANNEL A USBC-2/EX-2 WHEN 1, DISABLE WHEN 0 */
uint16_t S_A_UP:1; /*!< bit: 13 DN1 TO A & UP TO B WHEN 1, DN1 TO B & UP TO A WHEN 0 */
uint16_t HUB_RESET_N:1; /*!< bit: 14 RESET USB HUB WHEN 0, RUN WHEN 1 */
uint16_t HUB_CONNECT:1; /*!< bit: 15 SIGNAL VBUS CONNECT TO USB HUB WHEN 1 */
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} sr_exp_t;

View File

@@ -0,0 +1,28 @@
/*
Copyright 2019 Massdrop Inc.
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
//Macros to Enable, Disable, and Update USB 5V bus connections
#define USBC_CFG_5V1_VAR sr_exp_data.bit.E_VBUS_1 //Variable storing USBC-1 5V Bus state
#define USBC_CFG_5V1_ENA 1 //Value to enable USBC-1 5V Bus
#define USBC_CFG_5V1_DIS 0 //Value to disable USBC-1 5V Bus
#define USBC_CFG_5V1_UPDATE SR_EXP_WriteData() //Command to run to update value
#define USBC_CFG_5V2_VAR sr_exp_data.bit.E_VBUS_2 //Variable storing USBC-2 5V Bus state
#define USBC_CFG_5V2_ENA 1 //Value to enable USBC-1 5V Bus
#define USBC_CFG_5V2_DIS 0 //Value to disable USBC-1 5V Bus
#define USBC_CFG_5V2_UPDATE SR_EXP_WriteData() //Command to run to update value

View File

@@ -0,0 +1,107 @@
#include QMK_KEYBOARD_H
enum ctrl_keycodes {
U_T_AGCR = SAFE_RANGE, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
MD_BOOT, //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
keymap_config_t keymap_config;
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_HOME, KC_PGUP, KC_PAUS, \
KC_DEL, KC_END, KC_PGDN, KC_SLCK, \
KC_GRV, 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_NLCK, KC_PSLS, KC_PAST, KC_PSCR, \
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_P7, KC_P8, KC_P9, KC_PMNS, \
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_P4, KC_P5, KC_P6, KC_PPLS, \
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_P1, KC_P2, KC_P3, \
KC_UP, KC_PENT, \
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_P0, KC_PDOT, \
KC_LEFT, KC_DOWN, KC_RGHT \
),
[1] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, KC_MUTE, \
KC_MPRV, KC_MNXT, KC_VOLD, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, RGB_RMOD,RGB_VAD, RGB_MOD, RGB_HUD, RGB_SAD, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, RGB_TOG, _______, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______ \
),
/*
[X] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______ \
),
*/
};
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
switch (keycode) {
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
}
return false;
case DBG_MTRX:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_matrix, "Debug matrix");
}
return false;
case DBG_KBD:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_keyboard, "Debug keyboard");
}
return false;
case DBG_MOU:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_mouse, "Debug mouse");
}
return false;
case MD_BOOT:
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= 500) {
reset_keyboard();
}
}
return false;
default:
return true; //Process all other keycodes normally
}
}

View File

@@ -0,0 +1,294 @@
#include QMK_KEYBOARD_H
enum shift_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase
L_BRD, //LED Brightness Decrease
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next
L_PTP, //LED Pattern Select Previous
L_PSI, //LED Pattern Speed Increase
L_PSD, //LED Pattern Speed Decrease
L_T_MD, //LED Toggle Mode
L_T_ONF, //LED Toggle On / Off
L_ON, //LED On
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction and effect
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
DBG_FAC, //DEBUG Factory light testing (All on white)
MD_BOOT //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
keymap_config_t keymap_config;
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_HOME, KC_PGUP, KC_PAUS, \
KC_DEL, KC_END, KC_PGDN, KC_SLCK, \
KC_GRV, 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_NLCK, KC_PSLS, KC_PAST, KC_PSCR, \
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_P7, KC_P8, KC_P9, KC_PMNS, \
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_P4, KC_P5, KC_P6, KC_PPLS, \
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_P1, KC_P2, KC_P3, \
KC_UP, KC_PENT, \
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_P0, KC_PDOT, \
KC_LEFT, KC_DOWN, KC_RGHT \
),
[1] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, KC_MUTE, \
KC_MPRV, KC_MNXT, KC_VOLD, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
L_T_BR, L_PSD, L_BRI, L_PSI, L_EDG_I, _______, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, _______, _______, _______, _______, \
L_T_PTD, L_PTP, L_BRD, L_PTN, L_EDG_D, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, L_T_MD, L_T_ONF, _______, L_EDG_M, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, \
_______, _______, _______, DBG_FAC, KC_APP, _______, _______, _______, \
_______, _______, _______ \
),
/*
[X] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______ \
),
*/
};
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
static uint8_t scroll_effect = 0;
switch (keycode) {
case L_BRI:
if (record->event.pressed) {
if (LED_GCR_STEP > LED_GCR_MAX - gcr_desired) gcr_desired = LED_GCR_MAX;
else gcr_desired += LED_GCR_STEP;
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_BRD:
if (record->event.pressed) {
if (LED_GCR_STEP > gcr_desired) gcr_desired = 0;
else gcr_desired -= LED_GCR_STEP;
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_EDG_M:
if (record->event.pressed) {
led_edge_mode++;
if (led_edge_mode > LED_EDGE_MODE_MAX) {
led_edge_mode = LED_EDGE_MODE_ALL;
}
}
return false;
case L_EDG_I:
if (record->event.pressed) {
led_edge_brightness += 0.1;
if (led_edge_brightness > 1) { led_edge_brightness = 1; }
}
return false;
case L_EDG_D:
if (record->event.pressed) {
led_edge_brightness -= 0.1;
if (led_edge_brightness < 0) { led_edge_brightness = 0; }
}
return false;
case L_PTN:
if (record->event.pressed) {
if (led_animation_id == led_setups_count - 1) led_animation_id = 0;
else led_animation_id++;
}
return false;
case L_PTP:
if (record->event.pressed) {
if (led_animation_id == 0) led_animation_id = led_setups_count - 1;
else led_animation_id--;
}
return false;
case L_PSI:
if (record->event.pressed) {
led_animation_speed += ANIMATION_SPEED_STEP;
}
return false;
case L_PSD:
if (record->event.pressed) {
led_animation_speed -= ANIMATION_SPEED_STEP;
if (led_animation_speed < 0) led_animation_speed = 0;
}
return false;
case L_T_MD:
if (record->event.pressed) {
led_lighting_mode++;
if (led_lighting_mode > LED_MODE_MAX_INDEX) led_lighting_mode = LED_MODE_NORMAL;
}
return false;
case L_T_ONF:
if (record->event.pressed) {
I2C3733_Control_Set(!I2C3733_Control_Get());
}
return false;
case L_ON:
if (record->event.pressed) {
I2C3733_Control_Set(1);
}
return false;
case L_OFF:
if (record->event.pressed) {
I2C3733_Control_Set(0);
}
return false;
case L_T_BR:
if (record->event.pressed) {
led_animation_breathing = !led_animation_breathing;
if (led_animation_breathing) {
gcr_breathe = gcr_desired;
led_animation_breathe_cur = BREATHE_MIN_STEP;
breathe_dir = 1;
}
}
return false;
case L_T_PTD:
if (record->event.pressed) {
scroll_effect++;
if (scroll_effect == 1) { //Patterns with scroll move horizontal (Right to left)
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 0;
} else if (scroll_effect == 2) { //Patterns with scroll move vertical (Top to bottom)
led_animation_direction = 1;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 3) { //Patterns with scroll move vertical (Bottom to top)
led_animation_direction = 0;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 4) { //Patterns with scroll explode from center
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 1;
} else if (scroll_effect == 5) { //Patterns with scroll implode on center
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 1;
} else { //Patterns with scroll move horizontal (Left to right)
scroll_effect = 0;
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 0;
}
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_FAC:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
led_lighting_mode = LED_MODE_NORMAL;
led_edge_brightness = 1;
led_edge_mode = LED_EDGE_MODE_ALL;
led_animation_breathing = 0;
led_animation_id = 7; //led_programs.c led_setups leds_white index
gcr_desired = LED_GCR_MAX;
I2C3733_Control_Set(1);
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
}
return false;
case DBG_MTRX:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_matrix, "Debug matrix");
}
return false;
case DBG_KBD:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_keyboard, "Debug keyboard");
}
return false;
case DBG_MOU:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_mouse, "Debug mouse");
}
return false;
case MD_BOOT:
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}
return false;
default:
return true; //Process all other keycodes normally
}
}
led_instruction_t led_instructions[] = {
//LEDs are normally inactive, no processing is performed on them
//Flags are used in matching criteria for an LED to be active and indicate how to color it
//Flags can be found in tmk_core/protocol/arm_atsam/led_matrix.h (prefixed with LED_FLAG_)
//LED IDs can be found in config_led.h in the keyboard's directory
//Examples are below
//All LEDs use the user's selected pattern (this is the factory default)
{ .flags = LED_FLAG_USE_ROTATE_PATTERN },
//Specific LEDs use the user's selected pattern while all others are off
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_ROTATE_PATTERN, .id0 = 0xFFFFFFFF, .id1 = 0xAAAAAAAA, .id2 = 0x55555555, .id3 = 0x11111111 },
//Specific LEDs use specified RGB values while all others are off
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0xFF, .id1 = 0x00FF, .id2 = 0x0000FF00, .id3 = 0xFF000000, .r = 75, .g = 150, .b = 225 },
//All LEDs use the user's selected pattern
//On layer 1, all key LEDs (except the top row which keeps active pattern) are red while all edge LEDs are green
//When layer 1 is active, key LEDs use red (id0 32 - 17: 1111 1111 1111 1111 0000 0000 0000 0000 = 0xFFFF0000) (except top row 16 - 1)
//When layer 1 is active, key LEDs use red (id1 64 - 33: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
//When layer 1 is active, key LEDs use red (id2 87 - 65: 0000 0000 0111 1111 1111 1111 1111 1111 = 0x007FFFFF)
//When layer 1 is active, edge LEDs use green (id2 95 - 88: 1111 1111 1000 0000 0000 0000 0000 0000 = 0xFF800000)
//When layer 1 is active, edge LEDs use green (id3 119 - 96: 0000 0000 1111 1111 1111 1111 1111 1111 = 0x00FFFFFF)
// { .flags = LED_FLAG_USE_ROTATE_PATTERN },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_MATCH_LAYER | LED_FLAG_USE_RGB, .id0 = 0xFFFF0000, .id1 = 0xFFFFFFFF, .id2 = 0x007FFFFF, .r = 255, .layer = 1 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_MATCH_LAYER | LED_FLAG_USE_RGB, .id2 = 0xFF800000, .id3 = 0x00FFFFFF, .g = 127, .layer = 1 },
//All key LEDs use red while edge LEDs use the active pattern
//All key LEDs use red (id0 32 - 1: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
//All key LEDs use red (id1 64 - 33: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
//All key LEDs use red (id2 87 - 65: 0000 0000 0111 1111 1111 1111 1111 1111 = 0x007FFFFF)
//Edge uses active pattern (id2 95 - 88: 1111 1111 1000 0000 0000 0000 0000 0000 = 0xFF800000)
//Edge uses active pattern (id3 119 - 96: 0000 0000 1111 1111 1111 1111 1111 1111 = 0x00FFFFFF)
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0xFFFFFFFF, .id1 = 0xFFFFFFFF, .id2 = 0x007FFFFF, .r = 255 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_ROTATE_PATTERN , .id2 = 0xFF800000, .id3 = 0x00FFFFFF },
//end must be set to 1 to indicate end of instruction set
{ .end = 1 }
};

View File

@@ -0,0 +1,2 @@
# This keymap requires Massdrop Configurator support
OPT_DEFS += -DUSE_MASSDROP_CONFIGURATOR

View File

@@ -0,0 +1,264 @@
#include QMK_KEYBOARD_H
enum shift_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase
L_BRD, //LED Brightness Decrease
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next
L_PTP, //LED Pattern Select Previous
L_PSI, //LED Pattern Speed Increase
L_PSD, //LED Pattern Speed Decrease
L_T_MD, //LED Toggle Mode
L_T_ONF, //LED Toggle On / Off
L_ON, //LED On
L_OFF, //LED Off
L_T_BR, //LED Toggle Breath Effect
L_T_PTD, //LED Toggle Scrolling Pattern Direction and effect
U_T_AGCR, //USB Toggle Automatic GCR control
DBG_TOG, //DEBUG Toggle On / Off
DBG_MTRX, //DEBUG Toggle Matrix Prints
DBG_KBD, //DEBUG Toggle Keyboard Prints
DBG_MOU, //DEBUG Toggle Mouse Prints
DBG_FAC, //DEBUG Factory light testing (All on white)
MD_BOOT //Restart into bootloader after hold timeout
};
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
keymap_config_t keymap_config;
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_HOME, KC_PGUP, KC_PAUS, \
KC_DEL, KC_END, KC_PGDN, KC_SLCK, \
KC_GRV, 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_NLCK, KC_PSLS, KC_PAST, KC_PSCR, \
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_P7, KC_P8, KC_P9, KC_PMNS, \
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_P4, KC_P5, KC_P6, KC_PPLS, \
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_P1, KC_P2, KC_P3, \
KC_UP, KC_PENT, \
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(1), KC_P0, KC_PDOT, \
KC_LEFT, KC_DOWN, KC_RGHT \
),
[1] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, KC_MUTE, \
KC_MPRV, KC_MNXT, KC_VOLD, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
L_T_BR, L_PSD, L_BRI, L_PSI, L_EDG_I, _______, _______, _______, U_T_AGCR,_______, _______, _______, _______, _______, _______, _______, _______, _______, \
L_T_PTD, L_PTP, L_BRD, L_PTN, L_EDG_D, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, L_T_MD, L_T_ONF, _______, L_EDG_M, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, \
_______, _______, _______, DBG_FAC, KC_APP, _______, _______, _______, \
_______, _______, _______ \
),
/*
[X] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______ \
),
*/
};
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
};
#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
static uint32_t key_timer;
static uint8_t scroll_effect = 0;
switch (keycode) {
case L_BRI:
if (record->event.pressed) {
if (LED_GCR_STEP > LED_GCR_MAX - gcr_desired) gcr_desired = LED_GCR_MAX;
else gcr_desired += LED_GCR_STEP;
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_BRD:
if (record->event.pressed) {
if (LED_GCR_STEP > gcr_desired) gcr_desired = 0;
else gcr_desired -= LED_GCR_STEP;
if (led_animation_breathing) gcr_breathe = gcr_desired;
}
return false;
case L_EDG_M:
if (record->event.pressed) {
led_edge_mode++;
if (led_edge_mode > LED_EDGE_MODE_MAX) {
led_edge_mode = LED_EDGE_MODE_ALL;
}
}
return false;
case L_EDG_I:
if (record->event.pressed) {
led_edge_brightness += 0.1;
if (led_edge_brightness > 1) { led_edge_brightness = 1; }
}
return false;
case L_EDG_D:
if (record->event.pressed) {
led_edge_brightness -= 0.1;
if (led_edge_brightness < 0) { led_edge_brightness = 0; }
}
return false;
case L_PTN:
if (record->event.pressed) {
if (led_animation_id == led_setups_count - 1) led_animation_id = 0;
else led_animation_id++;
}
return false;
case L_PTP:
if (record->event.pressed) {
if (led_animation_id == 0) led_animation_id = led_setups_count - 1;
else led_animation_id--;
}
return false;
case L_PSI:
if (record->event.pressed) {
led_animation_speed += ANIMATION_SPEED_STEP;
}
return false;
case L_PSD:
if (record->event.pressed) {
led_animation_speed -= ANIMATION_SPEED_STEP;
if (led_animation_speed < 0) led_animation_speed = 0;
}
return false;
case L_T_MD:
if (record->event.pressed) {
led_lighting_mode++;
if (led_lighting_mode > LED_MODE_MAX_INDEX) led_lighting_mode = LED_MODE_NORMAL;
}
return false;
case L_T_ONF:
if (record->event.pressed) {
I2C3733_Control_Set(!I2C3733_Control_Get());
}
return false;
case L_ON:
if (record->event.pressed) {
I2C3733_Control_Set(1);
}
return false;
case L_OFF:
if (record->event.pressed) {
I2C3733_Control_Set(0);
}
return false;
case L_T_BR:
if (record->event.pressed) {
led_animation_breathing = !led_animation_breathing;
if (led_animation_breathing) {
gcr_breathe = gcr_desired;
led_animation_breathe_cur = BREATHE_MIN_STEP;
breathe_dir = 1;
}
}
return false;
case L_T_PTD:
if (record->event.pressed) {
scroll_effect++;
if (scroll_effect == 1) { //Patterns with scroll move horizontal (Right to left)
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 0;
} else if (scroll_effect == 2) { //Patterns with scroll move vertical (Top to bottom)
led_animation_direction = 1;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 3) { //Patterns with scroll move vertical (Bottom to top)
led_animation_direction = 0;
led_animation_orientation = 1;
led_animation_circular = 0;
} else if (scroll_effect == 4) { //Patterns with scroll explode from center
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 1;
} else if (scroll_effect == 5) { //Patterns with scroll implode on center
led_animation_direction = 1;
led_animation_orientation = 0;
led_animation_circular = 1;
} else { //Patterns with scroll move horizontal (Left to right)
scroll_effect = 0;
led_animation_direction = 0;
led_animation_orientation = 0;
led_animation_circular = 0;
}
}
return false;
case U_T_AGCR:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
}
return false;
case DBG_FAC:
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
led_lighting_mode = LED_MODE_NORMAL;
led_edge_brightness = 1;
led_edge_mode = LED_EDGE_MODE_ALL;
led_animation_breathing = 0;
led_animation_id = 7; //led_programs.c led_setups leds_white index
gcr_desired = LED_GCR_MAX;
I2C3733_Control_Set(1);
}
return false;
case DBG_TOG:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
}
return false;
case DBG_MTRX:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_matrix, "Debug matrix");
}
return false;
case DBG_KBD:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_keyboard, "Debug keyboard");
}
return false;
case DBG_MOU:
if (record->event.pressed) {
TOGGLE_FLAG_AND_PRINT(debug_mouse, "Debug mouse");
}
return false;
case MD_BOOT:
if (record->event.pressed) {
key_timer = timer_read32();
} else {
if (timer_elapsed32(key_timer) >= BOOTKEY_HOLD_MS) {
reset_keyboard();
}
}
return false;
default:
return true; //Process all other keycodes normally
}
}
led_instruction_t led_instructions[] = {
//Please see ../default_md/keymap.c for examples
//All LEDs use the user's selected pattern (this is the factory default)
{ .flags = LED_FLAG_USE_ROTATE_PATTERN },
//end must be set to 1 to indicate end of instruction set
{ .end = 1 }
};

View File

@@ -0,0 +1,211 @@
/*
Copyright 2019 Massdrop Inc.
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 "shift.h"
#include "d51_util.h"
#include "debug.h"
#include "clks.h"
#include "spi.h"
#include <string.h>
#define MCU_PORTS_USED 1 //PA
matrix_row_t mlatest[MATRIX_ROWS];
matrix_row_t mlast[MATRIX_ROWS];
matrix_row_t mdebounced[MATRIX_ROWS];
uint8_t row_ports[] = { MATRIX_ROW_PORTS };
uint8_t row_pins[] = { MATRIX_ROW_PINS };
uint8_t col_ports[] = { MATRIX_COL_PORTS };
uint8_t col_pins[] = { MATRIX_COL_PINS };
uint32_t row_masks[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
__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) {
}
void matrix_init(void)
{
SR_KC_Init();
memset(mlatest, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(mlast, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(mdebounced, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(row_masks, 0, sizeof(row_masks));
//Inputs
uint8_t row;
for (row = 0; row < MATRIX_ROWS; row++)
{
PORT->Group[row_ports[row]].DIRCLR.reg = 1 << row_pins[row]; //Input
PORT->Group[row_ports[row]].OUTCLR.reg = 1 << row_pins[row]; //Low
PORT->Group[row_ports[row]].PINCFG[row_pins[row]].bit.INEN = 1; //Input Enable,
PORT->Group[row_ports[row]].PINCFG[row_pins[row]].bit.PULLEN = 1; //Pull Enable
row_masks[row_ports[row]] |= 1 << row_pins[row]; //Add pin to proper row mask
}
//Outputs
uint8_t col;
for (col = 0; col < MATRIX_COLS; col++)
{
if (PORT_IS_MCU(col_ports[col])) //PORT_GROUPS from MCU's header file
{
PORT->Group[col_ports[col]].DIRSET.reg = 1 << col_pins[col]; //Output
PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Low
}
else if (PORT_IS_SR(col_ports[col])) //Pins on Shift Register
{
//Outputs Low
sr_kc_data.reg = 0;
SR_KC_WriteData();
}
}
matrix_init_quantum();
}
uint64_t mdebouncing = 0;
bool debouncing = false;
uint8_t matrix_scan(void)
{
uint64_t timer;
uint8_t row;
uint8_t col;
uint32_t scans[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
memset(mlatest, 0, MATRIX_ROWS * sizeof(matrix_row_t)); //Zero the result buffer
for (col = 0; col < MATRIX_COLS; col++)
{
//Set output
if (PORT_IS_MCU(col_ports[col])) //Pin is on MCU
{
PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; //Set col output
wait_us(1); //Delay for output
}
else if (PORT_IS_SR(col_ports[col])) //Pin is on Shift Register
{
sr_kc_data.reg |= (1 << col_pins[col]); //Set col output in RAM
SR_KC_WriteData(); //Write shift register update
wait_us(1); //Delay for output
}
else continue; //Bad configuration
//Read input (add unique ports as needed, PA, PB, PC, etc)
scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; //Read PA row pins data
//Clear output
if (PORT_IS_MCU(col_ports[col])) //Pin is on MCU
{
PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; //Clear col output
}
else if (PORT_IS_SR(col_ports[col])) //Pin is on Shift Register
{
sr_kc_data.reg &= ~(1 << col_pins[col]); //Clear col output in RAM
SR_KC_WriteData(); //Write shift register update
}
for (row = 0; row < MATRIX_ROWS; row++)
{
//Move scan bits from scans array into proper row bit locations
if (scans[row_ports[row]] & (1 << row_pins[row]))
mlatest[row] |= 1 << col;
}
}
timer = timer_read64();
for (row = 0; row < MATRIX_ROWS; row++)
{
if (mlast[row] != mlatest[row]) {
debouncing = true;
mdebouncing = timer + DEBOUNCE;
}
mlast[row] = mlatest[row];
}
if (debouncing && timer >= mdebouncing)
{
for (row = 0; row < MATRIX_ROWS; row++) {
mdebounced[row] = mlatest[row];
}
mdebouncing = 0;
debouncing = false;
}
matrix_scan_quantum();
return 1;
}
matrix_row_t matrix_get_row(uint8_t row)
{
return mdebounced[row];
}
void matrix_print(void)
{
char buf[(MATRIX_COLS+8)*(MATRIX_ROWS+1)] = "R C";
char *pbuf = buf+3;
uint32_t cols;
uint32_t rows;
matrix_row_t row;
for (cols = 1; cols <= MATRIX_COLS; cols++)
{
*pbuf = (cols%10)+48;
pbuf++;
}
*pbuf = '\r'; pbuf++;
*pbuf = '\n'; pbuf++;
for (rows = 1; rows <= MATRIX_ROWS; rows++)
{
row = matrix_get_row(rows-1);
if (rows < 10) { *pbuf = rows+48; pbuf++; *pbuf = ' '; pbuf++; *pbuf = ' '; pbuf++; }
else { *pbuf = (rows/10)+48; pbuf++; *pbuf = (rows%10)+48; pbuf++; *pbuf = ' '; pbuf++; }
for (cols = 0; cols < MATRIX_COLS; cols++)
{
if (row & 1 << cols) *pbuf = 'X';
else *pbuf = '.';
pbuf++;
}
*pbuf = '\r'; pbuf++;
*pbuf = '\n'; pbuf++;
}
*pbuf = 0;
dprint(buf);
}

View File

@@ -0,0 +1,77 @@
/*
Copyright 2011 Jun Wako <wakojun@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/>.
*/
#ifndef MATRIX_H
#define MATRIX_H
#include <stdint.h>
#include <stdbool.h>
#include "keyboard.h"
#if (MATRIX_COLS <= 8)
typedef uint8_t matrix_row_t;
#elif (MATRIX_COLS <= 16)
typedef uint16_t matrix_row_t;
#elif (MATRIX_COLS <= 32)
typedef uint32_t matrix_row_t;
#else
#error "MATRIX_COLS: invalid value"
#endif
#define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col))
#ifdef __cplusplus
extern "C" {
#endif
/* number of matrix rows */
uint8_t matrix_rows(void);
/* number of matrix columns */
uint8_t matrix_cols(void);
/* should be called at early stage of startup before matrix_init.(optional) */
void matrix_setup(void);
/* intialize matrix for scaning. */
void matrix_init(void);
/* scan all key states on matrix */
uint8_t matrix_scan(void);
/* whether modified from previous scan. used after matrix_scan. */
bool matrix_is_modified(void) __attribute__ ((deprecated));
/* whether a switch is on */
bool matrix_is_on(uint8_t row, uint8_t col);
/* matrix state on row */
matrix_row_t matrix_get_row(uint8_t row);
/* print matrix for debug */
void matrix_print(void);
/* power control */
void matrix_power_up(void);
void matrix_power_down(void);
/* executes code for Quantum */
void matrix_init_quantum(void);
void matrix_scan_quantum(void);
void matrix_init_kb(void);
void matrix_scan_kb(void);
void matrix_init_user(void);
void matrix_scan_user(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,38 @@
# project specific files
SRC = matrix.c
SRC += config_led.c
SRC += spi.c
SRC += usb.c
#For platform and packs
ARM_ATSAM = SAMD51J18A
MCU = cortex-m4
CUSTOM_MATRIX = yes
# Build Options
# comment out to disable the options.
#
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 = no # Console for debug(+400)
COMMAND_ENABLE = no # 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 = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality on B7 by default
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
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
HD44780_ENABLE = no # Enable support for HD44780 based LCDs (+400)
VIRTSER_ENABLE = no # USB Serial Driver
RAW_ENABLE = no # Raw device
AUTO_SHIFT_ENABLE = no # Auto Shift
# Custom RGB matrix handling
RGB_MATRIX_ENABLE = custom

View File

@@ -0,0 +1,40 @@
#pragma once
#include "quantum.h"
#include "config_led.h"
#include "matrix.h"
#include "i2c_master.h"
#include "led_matrix.h" //For led keycodes
#include "usb/udi_cdc.h"
#include "usb/usb2422.h"
#define LAYOUT( \
K001, K002, K003, K004, K005, K006, K007, K008, K009, K010, K011, K012, K013, \
K014, K015, K016, K017, K018, K019, K020, K021, K022, K023, K024, K025, K026, \
K027, K028, K029, K030, K031, K032, K033, K034, K035, K036, K037, K038, K039, \
K040, K041, K042, K043, K044, K045, K046, K047, K048, K049, K050, K051, K052, \
K053, K054, K055, K056, K057, K058, K059, K060, K061, K062, K063, K064, K065, \
K066, K067, K068, K069, K070, K071, K072, K073, K074, K075, K076, K077, K078, \
K079, K080, K081, K082, K083, K084, K085, K086, K087, K088, K089, K090, K091, \
K092, K093, K094, K095, K096, K097, K098, K099, K100, K101, K102 \
) { \
{ K001, K002, K003, K005, K006, K007, K008, K010, K012, K014, K015, K016, K017 }, \
{ K022, K023, K004, K027, K029, K030, K009, K011, K013, K018, K019, K020, K021 }, \
{ K040, K024, K025, K028, K046, K031, K032, K034, K035, K036, K037, K038, K039 }, \
{ K058, K041, K026, K044, K047, K048, K033, K051, K052, K054, K055, K056, K057 }, \
{ K075, K042, K043, K045, K064, K049, K050, K068, K053, K071, K072, K073, K074 }, \
{ K092, K059, K061, K062, K065, K066, K067, K084, K069, K087, K088, K089, K091 }, \
{ K093, K060, K077, K063, K080, K082, K083, K085, K070, K090, K102, K098, K099 }, \
{ K094, K076, K078, K079, K095, K081, K096, K097, K086, K100, K101, KC_NO, KC_NO } \
}
#define TOGGLE_FLAG_AND_PRINT(var, name) { \
if (var) { \
dprintf(name " disabled\r\n"); \
var = !var; \
} else { \
var = !var; \
dprintf(name " enabled\r\n"); \
} \
}

View File

@@ -0,0 +1,60 @@
/*
Copyright 2019 Massdrop Inc.
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 "arm_atsam_protocol.h"
void SR_EXP_Init_kb(void) {
/* Initialize shift register */
SR_EXP_OE_N_DIS;
SR_EXP_RCLK_HI;
SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; //Data Order - LSB is transferred first
SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; //Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; //Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3; //Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; //Data Output PAD[0], Serial Clock PAD[1]
SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; //Operating Mode - Master operation
SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; //Enable - Peripheral is enabled or being enabled
while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { DBGC(DC_SPI_EXP_SYNC_ENABLING); }
/* Set default shift register values */
sr_exp_data.reg = 0; //Clear data register
sr_exp_data.bit.HUB_CONNECT = 0; //USB Hub disconnected
sr_exp_data.bit.HUB_RESET_N = 0; //USB Hub in reset state
sr_exp_data.bit.SRC_1_A5 = 1; //Set CON1 CC A5 as Rd 5.1k
sr_exp_data.bit.SRC_1_B5 = 1; //Set CON1 CC B5 as Rd 5.1k
sr_exp_data.bit.SRC_2_A5 = 1; //Set CON2 CC A5 as Rd 5.1k
sr_exp_data.bit.SRC_2_B5 = 1; //Set CON2 CC B5 as Rd 5.1k
sr_exp_data.bit.S_A_UP = 0; //0 = DN1 to A and UP to B, 1 = DN1 to B and UP to A
sr_exp_data.bit.S_A_EXT = 1; //1 = Onboard, 0 = Offboard
sr_exp_data.bit.S_B_EXT = 0; //0 = Onboard, 1 = Offboard
sr_exp_data.bit.ENB = 0; //Disable CON1
sr_exp_data.bit.ENA = 0; //Disable CON2
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
sr_exp_data.bit.IRST = 1; //LED drivers I2C in reset
sr_exp_data.bit.SDB_N = 0; //LED drivers in shutdown
/* Write shift register data */
SR_EXP_WriteData();
/* Enable shift register output */
SR_EXP_OE_N_ENA;
}

View File

@@ -0,0 +1,119 @@
/*
Copyright 2019 Massdrop Inc.
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 "arm_atsam_protocol.h"
void usb_set_host_kb(uint8_t con, uint8_t rp_best_index) {
if (con == 1) {
//DN1 to A (CON2/EX2), UP to B (CON1/EX1)
sr_exp_data.bit.S_A_UP = 1; //0 = DN1 to B and UP to A, 1 = DN1 to A and UP to B (SAI-SBI)
if (ADC_USBC_IS_ONB(rp_best_index)) { //Check if the port detected is onboard
sr_exp_data.bit.S_B_EXT = 0; //Onboard port
g_usb_host_port = USB_HOST_PORT_1; //Save host port
} else { //Port is external
sr_exp_data.bit.S_B_EXT = 1; //External port
g_usb_host_port = USB_HOST_PORT_1_EXT; //Save host port
}
sr_exp_data.bit.E_VBUS_1 = 1; //Enable CON1 5V
SR_EXP_WriteData(); //Update port configuration
} else if (con == 2) {
//DN1 to B (CON1/EX1), UP to A (CON2/EX2)
sr_exp_data.bit.S_A_UP = 0; //0 = DN1 to B and UP to A, 1 = DN1 to A and UP to B (SAI-SBI)
if (ADC_USBC_IS_ONB(rp_best_index)) { //Check if the port detected is onboard
sr_exp_data.bit.S_A_EXT = 1; //Onboard port
g_usb_host_port = USB_HOST_PORT_2; //Save host port
} else { //Port is external
sr_exp_data.bit.S_A_EXT = 0; //External port
g_usb_host_port = USB_HOST_PORT_2_EXT; //Save host port
}
sr_exp_data.bit.E_VBUS_2 = 1; //Enable CON2 5V
SR_EXP_WriteData(); //Update port configuration
}
}
void usb_set_extra_kb(uint8_t con) {
if (con == 1) {
sr_exp_data.bit.SRC_1_A5 = 0; //Set CON1 CC A5 as Rp 56k
sr_exp_data.bit.SRC_1_B5 = 0; //Set CON1 CC B5 as Rp 56k
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
SR_EXP_WriteData(); //Update port configuration
} else if (con == 2) {
sr_exp_data.bit.SRC_2_A5 = 0; //Set CON2 CC A5 as Rp 56k
sr_exp_data.bit.SRC_2_B5 = 0; //Set CON2 CC B5 as Rp 56k
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
SR_EXP_WriteData(); //Update port configuration
}
}
void usb_init_host_detection_kb(void) {
//Disable 5V
sr_exp_data.bit.E_VBUS_1 = 0; //Disable CON1 5V
sr_exp_data.bit.E_VBUS_2 = 0; //Disable CON2 5V
//Configure default paths
sr_exp_data.bit.S_A_UP = 0; //DN1 TO A & UP TO B WHEN 1, DN1 TO B & UP TO A WHEN 0
sr_exp_data.bit.S_A_EXT = 1; //1 = Onboard, 0 = Offboard (SAO)
sr_exp_data.bit.S_B_EXT = 0; //0 = Onboard, 1 = Offboard (SBO)
//Configure CC lines
sr_exp_data.bit.SRC_1_A5 = 1; //Set CON1 CC A5 as Rd 5.1k
sr_exp_data.bit.SRC_1_B5 = 1; //Set CON1 CC B5 as Rd 5.1k
sr_exp_data.bit.SRC_2_A5 = 1; //Set CON2 CC A5 as Rd 5.1k
sr_exp_data.bit.SRC_2_B5 = 1; //Set CON2 CC B5 as Rd 5.1k
//Enable ports
sr_exp_data.bit.ENB = 1; //Enable CON1/EX1 for use
sr_exp_data.bit.ENA = 1; //Enable CON2/EX2 for use
SR_EXP_WriteData(); //Update port configuration
}
//Return 1 if configuration successful
//Return 0 otherwise
uint8_t usb_attach_port_configure_kb(uint8_t g_usb_host_port, uint16_t usbc_cc_a5_v, uint16_t usbc_cc_b5_v) {
if (USB_HOST_IS_1(g_usb_host_port)) { //If host is port 1
//Set up port 2
if (USBC_IS_SINK_ONB(usbc_cc_a5_v, usbc_cc_b5_v)) { //If onboard port detected
sr_exp_data.bit.S_A_EXT = 1; //Set port 2 as onboard port
SR_EXP_WriteData(); //Update port configuration
return 1;
} else if (USBC_IS_SINK_EXT(usbc_cc_a5_v, usbc_cc_b5_v)) { //If external port detected
sr_exp_data.bit.S_A_EXT = 0; //Set port 2 as onboard port
SR_EXP_WriteData(); //Update port configuration
return 1;
}
} else if (USB_HOST_IS_2(g_usb_host_port)) { //If host is on port 2
//Set up port 1
if (USBC_IS_SINK_ONB(usbc_cc_a5_v, usbc_cc_b5_v)) { //If onboard port detected
sr_exp_data.bit.S_B_EXT = 0; //Set port 1 as onboard port
SR_EXP_WriteData(); //Update port configuration
return 1;
} else if (USBC_IS_SINK_EXT(usbc_cc_a5_v, usbc_cc_b5_v)) { //If external port detected
sr_exp_data.bit.S_B_EXT = 1; //Set port 1 as external port
SR_EXP_WriteData(); //Update port configuration
return 1;
}
}
return 0;
}

View File

@@ -647,6 +647,7 @@ bool process_record_quantum(keyrecord_t *record) {
#endif
break;
case MAGIC_TOGGLE_NKRO:
clear_keyboard(); // clear first buffer to prevent stuck keys -PS080919
keymap_config.nkro = !keymap_config.nkro;
break;
default:

View File

@@ -79,9 +79,10 @@ void suspend_wakeup_init_kb(void) {
void suspend_wakeup_init(void) {
#ifdef RGB_MATRIX_ENABLE
#ifdef USE_MASSDROP_CONFIGURATOR
if (led_enabled) {
// TODO: need to re-add led_enabled?
// if (I2C3733_Control_Get()) {
I2C3733_Control_Set(1);
}
// }
#else
I2C3733_Control_Set(1);
#endif

View File

@@ -9,6 +9,7 @@ ifeq ($(RGB_MATRIX_ENABLE),custom)
SRC += $(ARM_ATSAM_DIR)/led_matrix.c
endif
SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c
SRC += $(ARM_ATSAM_DIR)/power.c
SRC += $(ARM_ATSAM_DIR)/spi.c
SRC += $(ARM_ATSAM_DIR)/startup.c

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -17,13 +17,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "arm_atsam_protocol.h"
uint16_t v_5v;
uint16_t v_5v_avg;
uint16_t v_con_1;
uint16_t v_con_2;
uint16_t v_con_1_boot;
uint16_t v_con_2_boot;
//Configuration in keyboard's config_adc.h
uint8_t adc_config[][ADC_SAMPLEN + 1] = {
{ ADC_CONFIG_5V },
{ ADC_CONFIG_C1A5 },
{ ADC_CONFIG_C1B5 },
{ ADC_CONFIG_C2A5 },
{ ADC_CONFIG_C2B5 },
{ ADC_CONFIG_C1I },
{ ADC_CONFIG_C2I }
};
#ifdef ADC_USBC_RP_DELTA_MAX
uint16_t adc_usbc_rp_nominal[ADC_USBC_RP_TYPES * ADC_USBC_CON_TYPES] = { ADC_USBC_RP_NOM };
#endif
uint16_t g_v_5v;
float g_v_5v_avg;
__attribute__ ((weak))
void ADC0_clock_init(void)
{
DBGC(DC_ADC0_CLOCK_INIT_BEGIN);
@@ -36,64 +48,174 @@ void ADC0_clock_init(void)
DBGC(DC_ADC0_CLOCK_INIT_COMPLETE);
}
void ADC0_init(void)
__attribute__ ((weak))
void ADC1_clock_init(void)
{
DBGC(DC_ADC0_INIT_BEGIN);
DBGC(DC_ADC1_CLOCK_INIT_BEGIN);
//MCU
PORT->Group[1].DIRCLR.reg = 1 << 0; //PB00 as input 5V
PORT->Group[1].DIRCLR.reg = 1 << 1; //PB01 as input CON2
PORT->Group[1].DIRCLR.reg = 1 << 2; //PB02 as input CON1
PORT->Group[1].PMUX[0].bit.PMUXE = 1; //PB00 mux select B ADC 5V
PORT->Group[1].PMUX[0].bit.PMUXO = 1; //PB01 mux select B ADC CON2
PORT->Group[1].PMUX[1].bit.PMUXE = 1; //PB02 mux select B ADC CON1
PORT->Group[1].PINCFG[0].bit.PMUXEN = 1; //PB01 mux ADC Enable 5V
PORT->Group[1].PINCFG[1].bit.PMUXEN = 1; //PB01 mux ADC Enable CON2
PORT->Group[1].PINCFG[2].bit.PMUXEN = 1; //PB02 mux ADC Enable CON1
MCLK->APBDMASK.bit.ADC1_ = 1; //ADC1 Clock Enable
//ADC
ADC0->CTRLA.bit.SWRST = 1;
while (ADC0->SYNCBUSY.bit.SWRST) { DBGC(DC_ADC0_SWRST_SYNCING_1); }
while (ADC0->CTRLA.bit.SWRST) { DBGC(DC_ADC0_SWRST_SYNCING_2); }
GCLK->PCHCTRL[ADC1_GCLK_ID].bit.GEN = GEN_OSC0; //Select generator clock
GCLK->PCHCTRL[ADC1_GCLK_ID].bit.CHEN = 1; //Enable peripheral clock
//Clock divide
ADC0->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV2_Val;
DBGC(DC_ADC1_CLOCK_INIT_COMPLETE);
}
//Averaging
ADC0->AVGCTRL.bit.SAMPLENUM = ADC_AVGCTRL_SAMPLENUM_4_Val;
while (ADC0->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC0_AVGCTRL_SYNCING_1); }
if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_1_Val) ADC0->AVGCTRL.bit.ADJRES = 0;
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_2_Val) ADC0->AVGCTRL.bit.ADJRES = 1;
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_4_Val) ADC0->AVGCTRL.bit.ADJRES = 2;
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_8_Val) ADC0->AVGCTRL.bit.ADJRES = 3;
else ADC0->AVGCTRL.bit.ADJRES = 4;
while (ADC0->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC0_AVGCTRL_SYNCING_2); }
//Settling
ADC0->SAMPCTRL.bit.SAMPLEN = 45; //Sampling Time Length: 1-63, 1 ADC CLK per
while (ADC0->SYNCBUSY.bit.SAMPCTRL) { DBGC(DC_ADC0_SAMPCTRL_SYNCING_1); }
//Load factory calibration data
__attribute__ ((weak))
void ADC0_load_cal(void)
{
ADC0->CALIB.bit.BIASCOMP = ((*(uint32_t *)ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
ADC0->CALIB.bit.BIASR2R = ((*(uint32_t *)ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
ADC0->CALIB.bit.BIASREFBUF = ((*(uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
//Enable
ADC0->CTRLA.bit.ENABLE = 1;
while (ADC0->SYNCBUSY.bit.ENABLE) { DBGC(DC_ADC0_ENABLE_SYNCING_1); }
DBGC(DC_ADC0_INIT_COMPLETE);
}
uint16_t adc_get(uint8_t muxpos)
__attribute__ ((weak))
void ADC1_load_cal(void)
{
ADC0->INPUTCTRL.bit.MUXPOS = muxpos;
while (ADC0->SYNCBUSY.bit.INPUTCTRL) {}
ADC0->SWTRIG.bit.START = 1;
while (ADC0->SYNCBUSY.bit.SWTRIG) {}
while (!ADC0->INTFLAG.bit.RESRDY) {}
return ADC0->RESULT.reg;
ADC1->CALIB.bit.BIASCOMP = ((*(uint32_t *)ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
ADC1->CALIB.bit.BIASR2R = ((*(uint32_t *)ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
ADC1->CALIB.bit.BIASREFBUF = ((*(uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
}
__attribute__ ((weak))
void ADC_init(void)
{
uint8_t adc_configured[ADC_INST_NUM] = { 0 };
uint8_t mcu_port;
uint8_t mcu_pin;
uint8_t mcu_mux;
uint8_t adc_index;
PortGroup *port;
uint8_t adc_row;
for (adc_row = 0; adc_row < sizeof(adc_config) / sizeof(adc_config[0]); adc_row++)
{
DBGC(DC_ADC_INIT_BEGIN);
mcu_port = adc_config[adc_row][ADC_PORT];
if (mcu_port == (uint8_t)ADC_NA)
{
continue; //ADC not available
}
adc_index = adc_config[adc_row][ADC_INDEX];
mcu_pin = adc_config[adc_row][ADC_PIN];
mcu_mux = adc_config[adc_row][ADC_MUX];
port = &PORT->Group[mcu_port];
//Set up MCU pins
port->DIRCLR.reg = 1 << mcu_pin; //PIN as input
if (mcu_pin / 2 == 0)
{
port->PMUX[mcu_pin / 2].bit.PMUXE = mcu_mux; //Set MUX
}
else
{
port->PMUX[mcu_pin / 2].bit.PMUXO = mcu_mux; //Set MUX
}
port->PINCFG[mcu_pin].bit.PMUXEN = 1; //Enable MUX
//Configure ADC if it has not been already
if (adc_configured[adc_index] != 1)
{
ADC_configure(adc_index);
adc_configured[adc_row] = 1;
}
DBGC(DC_ADC_INIT_COMPLETE);
}
}
__attribute__ ((weak))
void ADC_configure(uint8_t adc_index)
{
Adc *adc_insts[] = ADC_INSTS;
Adc *adc = adc_insts[adc_index];
//Reset the ADC
adc->CTRLA.bit.SWRST = 1;
while (adc->SYNCBUSY.bit.SWRST) { DBGC(DC_ADC_SWRST_SYNCING_1); }
while (adc->CTRLA.bit.SWRST) { DBGC(DC_ADC_SWRST_SYNCING_2); }
//Configure clock divide
adc->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV2_Val;
//Load factory calibration data
if (adc_index == 0)
{
ADC0_load_cal();
ADC0_clock_init();
}
else if (adc_index == 1)
{
ADC1_load_cal();
ADC1_clock_init();
}
//Enable the ADC
adc->CTRLA.bit.ENABLE = 1;
while (adc->SYNCBUSY.bit.ENABLE) { DBGC(DC_ADC_ENABLE_SYNCING_1); }
}
//Return ADC_NA if the ADC is not available
//Return ADC counts otherwise
__attribute__ ((weak))
uint16_t adc_get(uint8_t adc_id)
{
uint16_t result = 0;
//Make sure ADC is available
if (adc_config[adc_id][ADC_PORT] == (uint8_t)ADC_NA)
{
result = (uint16_t)ADC_NA;
}
else
{
Adc *adc_insts[] = ADC_INSTS;
Adc *adc = adc_insts[adc_config[adc_id][ADC_INDEX]];
adc->INPUTCTRL.bit.MUXPOS = adc_config[adc_id][ADC_MUXPOS];
while (adc->SYNCBUSY.bit.INPUTCTRL) { DBGC(DC_ADC_GET_INPUTCTRL_SYNCING_1); }
//Only switch reference if not already selected
if (adc->REFCTRL.bit.REFSEL != adc_config[adc_id][ADC_REFSEL])
{
adc->REFCTRL.bit.REFSEL = adc_config[adc_id][ADC_REFSEL];
while (adc->SYNCBUSY.bit.REFCTRL) { DBGC(DC_ADC_GET_REFCTRL_SYNCING_1); }
}
//Configure averaging
if (adc->AVGCTRL.bit.SAMPLENUM != adc_config[adc_id][ADC_SAMPLENUM])
{
adc->AVGCTRL.bit.SAMPLENUM = adc_config[adc_id][ADC_SAMPLENUM];
while (adc->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC_GET_AVGCTRL_SYNCING_1); }
if (adc->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_1_Val) adc->AVGCTRL.bit.ADJRES = 0;
else if (adc->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_2_Val) adc->AVGCTRL.bit.ADJRES = 1;
else if (adc->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_4_Val) adc->AVGCTRL.bit.ADJRES = 2;
else if (adc->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_8_Val) adc->AVGCTRL.bit.ADJRES = 3;
else adc->AVGCTRL.bit.ADJRES = 4;
while (adc->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC_GET_AVGCTRL_SYNCING_2); }
}
//Configure settling
if (adc->SAMPCTRL.bit.SAMPLEN != adc_config[adc_id][ADC_SAMPLEN])
{
adc->SAMPCTRL.bit.SAMPLEN = adc_config[adc_id][ADC_SAMPLEN];
while (adc->SYNCBUSY.bit.SAMPCTRL) { DBGC(DC_ADC_GET_SAMPCTRL_SYNCING_1); }
}
adc->SWTRIG.bit.START = 1;
while (adc->SYNCBUSY.bit.SWTRIG) { DBGC(DC_ADC_GET_SWTRIG_SYNCING_1); }
while (!adc->INTFLAG.bit.RESRDY) { DBGC(DC_ADC_GET_INTFLAG_RESRDY_WAITING_1); }
result = adc->RESULT.reg;
//In the case of a 16-bit ADC, a maxed out reading becomes a return of "ADC not available", so take off one count
if (result == (uint16_t)ADC_NA)
{
result--;
}
}
return result;
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -18,20 +18,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef _ADC_H_
#define _ADC_H_
#define ADC_5V_START_LEVEL 2365
#include "config_adc.h" //From keyboard's directory
#define ADC_5V ADC_INPUTCTRL_MUXPOS_AIN12_Val
#define ADC_CON1 ADC_INPUTCTRL_MUXPOS_AIN14_Val
#define ADC_CON2 ADC_INPUTCTRL_MUXPOS_AIN13_Val
#define ADC_NA -1 //Value to mark an ADC as not available for use and return from an acquire
#define ADC_5V_START_LEVEL 4.75f //In volts, system will wait until voltage is greater than this
extern uint16_t v_5v;
extern uint16_t v_5v_avg;
extern uint16_t v_con_1;
extern uint16_t v_con_2;
extern uint16_t v_con_1_boot;
extern uint16_t v_con_2_boot;
extern uint16_t g_v_5v;
extern float g_v_5v_avg;
void ADC0_clock_init(void);
void ADC0_init(void);
void ADC_init(void);
void ADC_configure(uint8_t adc_index);
uint16_t adc_get(uint8_t adc_id);
#endif //_ADC_H_

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -15,19 +15,29 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARM_ATSAM_PROTOCOL_H_
#define _ARM_ATSAM_PROTOCOL_H_
#pragma once
#include "samd51j18a.h"
#include "md_bootloader.h"
#include "timer.h"
#ifdef MD_BOOTLOADER
#include <stdlib.h> //For abs()
#include "config.h" //From keyboard's directory
#endif
#include "md_bootloader.h"
#include "d51_util.h"
#include "clks.h"
#include "quantum.h"
#include "timer.h"
#include "wait.h"
#include "clks.h"
#include "adc.h"
#include "i2c_master.h"
#include "spi.h"
#include "power.h"
#include "./usb/usb2422.h"
@@ -44,6 +54,3 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "./usb/udi_cdc.h"
#endif //MD_BOOTLOADER
#endif //_ARM_ATSAM_PROTOCOL_H_

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -291,6 +291,9 @@ void clk_enable_sercom_apbmask(int sercomn)
case 3:
pmclk->APBBMASK.bit.SERCOM3_ = 1;
break;
case 4:
pmclk->APBDMASK.bit.SERCOM4_ = 1;
break;
default:
break;
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef MD_BOOTLOADER
#include "samd51j18a.h"
//From keyboard
#include "config_led.h"
#include "config.h"
@@ -28,33 +30,29 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define PLL_RATIO 47 //mcu frequency ((X+1)MHz)
#define FREQ_DFLL_DEFAULT 48000000 //DFLL frequency / usb clock
#define FREQ_SPI_DEFAULT 1000000 //spi to 595 shift regs
#define FREQ_SPI_DEFAULT 12000000 //spi to 595 shift regs
#ifdef SR_KC_SERCOM_NUM
#define FREQ_SPI_KC_DEFAULT 12000000 //spi to 595 shift regs for kc
#endif
#define FREQ_I2C0_DEFAULT 100000 //i2c to hub
#define FREQ_I2C1_DEFAULT I2C_HZ //i2c to LED drivers
#define FREQ_I2C1_DEFAULT I2C_HZ //i2c to LED drivers (keyboard's configuration files)
#define FREQ_TC45_DEFAULT 1000000 //1 usec resolution
#define FREQ_XOSC0 16000000 //Frequency of the external oscillator
//I2C1 Set ~Result PWM Time (2x Drivers)
// 1000000 1090000
// 900000 1000000 3.82ms
// 800000 860000
// 700000 750000
// 600000 630000
// 580000 615000 6.08ms
// 500000 522000
#define FREQ_XOSC0 16000000
#define CHAN_SERCOM_SPI 2 //shift regs
#define CHAN_SERCOM_I2C0 0 //hub
#define CHAN_SERCOM_I2C1 1 //led drivers
#define CHAN_SERCOM_UART 3 //debug util
#define CHAN_SERCOM_SPI_EXP SR_EXP_SERCOM_NUM //shift regs
#ifdef SR_KC_SERCOM_NUM
#define CHAN_SERCOM_SPI_KC SR_KC_SERCOM_NUM //key column drive
#endif
#define CHAN_SERCOM_I2C0 0 //hub
#define CHAN_SERCOM_I2C1 1 //led drivers
#define CHAN_SERCOM_UART 3 //debug util
//Generator clock channels
#define GEN_DPLL0 0
#define GEN_OSC0 1
#define GEN_TC45 2
#define SERCOM_COUNT 5
#define SERCOM_COUNT SERCOM_INST_NUM
#define GCLK_COUNT 12
typedef struct clk_s {

View File

@@ -1,7 +1,7 @@
#include "d51_util.h"
#include "arm_atsam_protocol.h"
static volatile uint32_t w;
//Display unsigned 32-bit number by port toggling DBG_1 (to view on a scope)
//Read as follows: 1230 = | | | | | | || (note zero is fast double toggle)
#define DBG_PAUSE 5

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -15,8 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _D51_UTIL_H_
#define _D51_UTIL_H_
#pragma once
#include "samd51j18a.h"
@@ -42,7 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#else
#define DBG_1_ENA
#define DBG_1_DIS
#define DBG_1_ON
#define DBG_1_ON
#define DBG_1_OFF
#endif
@@ -55,7 +54,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#else
#define DBG_2_ENA
#define DBG_2_DIS
#define DBG_2_ON
#define DBG_2_ON
#define DBG_2_OFF
#endif
@@ -68,7 +67,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#else
#define DBG_3_ENA
#define DBG_3_DIS
#define DBG_3_ON
#define DBG_3_ON
#define DBG_3_OFF
#endif
@@ -144,20 +143,20 @@ enum debug_code_list {
DC_CLK_OSC_INIT_DPLL_WAIT_CLKRDY,
DC_CLK_OSC_INIT_GCLK_SYNC_GENCTRL0,
DC_CLK_OSC_INIT_COMPLETE,
DC_SPI_INIT_BEGIN,
DC_SPI_WRITE_DRE,
DC_SPI_WRITE_TXC_1,
DC_SPI_WRITE_TXC_2,
DC_SPI_SYNC_ENABLING,
DC_SPI_INIT_COMPLETE,
DC_SPI_EXP_INIT_BEGIN,
DC_SPI_EXP_WRITE_DRE,
DC_SPI_EXP_WRITE_TXC_1,
DC_SPI_EXP_WRITE_TXC_2,
DC_SPI_EXP_SYNC_ENABLING,
DC_SPI_EXP_INIT_COMPLETE,
DC_PORT_DETECT_INIT_BEGIN,
DC_PORT_DETECT_INIT_FAILED,
DC_PORT_DETECT_INIT_COMPLETE,
DC_USB_RESET_BEGIN,
DC_USB_RESET_COMPLETE,
DC_USB_SET_HOST_BY_VOLTAGE_BEGIN,
DC_USB_SET_HOST_5V_LOW_WAITING,
DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE,
DC_USB_DETECT_HOST_BEGIN,
DC_USB_DETECT_HOST_5V_LOW_WAITING,
DC_USB_DETECT_HOST_COMPLETE,
DC_USB_CONFIGURE_BEGIN,
DC_USB_CONFIGURE_GET_SERIAL,
DC_USB_CONFIGURE_COMPLETE,
@@ -166,14 +165,14 @@ enum debug_code_list {
DC_USB_WRITE2422_BLOCK_COMPLETE,
DC_ADC0_CLOCK_INIT_BEGIN,
DC_ADC0_CLOCK_INIT_COMPLETE,
DC_ADC0_INIT_BEGIN,
DC_ADC0_SWRST_SYNCING_1,
DC_ADC0_SWRST_SYNCING_2,
DC_ADC0_AVGCTRL_SYNCING_1,
DC_ADC0_AVGCTRL_SYNCING_2,
DC_ADC0_SAMPCTRL_SYNCING_1,
DC_ADC0_ENABLE_SYNCING_1,
DC_ADC0_INIT_COMPLETE,
DC_ADC_INIT_BEGIN,
DC_ADC_SWRST_SYNCING_1,
DC_ADC_SWRST_SYNCING_2,
DC_ADC_GET_AVGCTRL_SYNCING_1,
DC_ADC_GET_AVGCTRL_SYNCING_2,
DC_ADC_GET_SAMPCTRL_SYNCING_1,
DC_ADC_ENABLE_SYNCING_1,
DC_ADC_INIT_COMPLETE,
DC_I2C0_INIT_BEGIN,
DC_I2C0_INIT_SYNC_ENABLING,
DC_I2C0_INIT_SYNC_SYSOP,
@@ -211,6 +210,18 @@ enum debug_code_list {
DC_MAIN_UDC_START_COMPLETE,
DC_MAIN_CDC_INIT_BEGIN,
DC_MAIN_CDC_INIT_COMPLETE,
DC_SPI_KC_INIT_BEGIN,
DC_SPI_KC_WRITE_DRE,
DC_SPI_KC_WRITE_TXC_1,
DC_SPI_KC_WRITE_TXC_2,
DC_SPI_KC_SYNC_ENABLING,
DC_SPI_KC_INIT_COMPLETE,
DC_ADC1_CLOCK_INIT_BEGIN,
DC_ADC1_CLOCK_INIT_COMPLETE,
DC_ADC_GET_INPUTCTRL_SYNCING_1,
DC_ADC_GET_REFCTRL_SYNCING_1,
DC_ADC_GET_SWTRIG_SYNCING_1,
DC_ADC_GET_INTFLAG_RESRDY_WAITING_1
/* Never change the order of error codes! Only add codes to end! */
};
@@ -219,5 +230,3 @@ enum debug_code_list {
#define DBGC(n) {}
#endif //DEBUG_BOOT_TRACING_ENABLE
#endif //_D51_UTIL_H_

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -120,10 +120,10 @@ void i2c1_init(void)
CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
/* MCU */
PORT->Group[0].PMUX[8].bit.PMUXE = 2;
PORT->Group[0].PMUX[8].bit.PMUXO = 2;
PORT->Group[0].PINCFG[16].bit.PMUXEN = 1;
PORT->Group[0].PINCFG[17].bit.PMUXEN = 1;
PORT->Group[0].PMUX[8].bit.PMUXE = 2; //PA16 even
PORT->Group[0].PMUX[8].bit.PMUXO = 2; //PA17 odd
PORT->Group[0].PINCFG[16].bit.PMUXEN = 1; //PA16
PORT->Group[0].PINCFG[17].bit.PMUXEN = 1; //PA17
/* I2C */
//Note: SW Reset handled in CLK_set_i2c1_freq clks.c
@@ -214,15 +214,11 @@ void i2c_led_send_GCR(uint8_t drvid)
void i2c_led_send_onoff(uint8_t drvid)
{
#if I2C_LED_USE_DMA != 1
if (!i2c_led_q_running)
{
#endif
i2c_led_send_CRWL(drvid);
i2c_led_select_page(drvid, 0);
#if I2C_LED_USE_DMA != 1
}
#endif
*issidrv[drvid].onoff = 0; //Force start location offset to zero
i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].onoff, ISSI3733_PG0_BYTES, 0);
@@ -243,15 +239,11 @@ void i2c_led_send_pur_pdr(uint8_t drvid, uint8_t pur, uint8_t pdr)
void i2c_led_send_pwm(uint8_t drvid)
{
#if I2C_LED_USE_DMA != 1
if (!i2c_led_q_running)
{
#endif
i2c_led_send_CRWL(drvid);
i2c_led_select_page(drvid, 0);
#if I2C_LED_USE_DMA != 1
i2c_led_select_page(drvid, 1);
}
#endif
*issidrv[drvid].pwm = 0; //Force start location offset to zero
i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].pwm, ISSI3733_PG1_BYTES, 0);
@@ -292,18 +284,21 @@ uint8_t I2C3733_Init_Drivers(void)
i2c_led_select_page(0, 3);
i2c_led_send_mode_op_gcr(0, 0, ISSI3733_CR_SSD_NORMAL); //No SYNC due to brightness mismatch with second driver
//Set up slave device
i2c_led_send_CRWL(1);
i2c_led_select_page(1, 3);
i2c_led_send_mode_op_gcr(1, 0, ISSI3733_CR_SSD_NORMAL); //No SYNC due to brightness mismatch with first driver and slight flicker at rgb values 1,2
i2c_led_send_CRWL(0);
i2c_led_select_page(0, 3);
i2c_led_send_pur_pdr(0, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
i2c_led_send_CRWL(1);
i2c_led_select_page(1, 3);
i2c_led_send_pur_pdr(1, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
//Set up slave devices
for (uint8_t drvid = 1; drvid < ISSI3733_DRIVER_COUNT; drvid++)
{
i2c_led_send_CRWL(drvid);
i2c_led_select_page(drvid, 3);
i2c_led_send_mode_op_gcr(drvid, 0, ISSI3733_CR_SSD_NORMAL); //No SYNC due to brightness mismatch with master driver and slight flicker at rgb values 1,2
i2c_led_send_CRWL(drvid);
i2c_led_select_page(drvid, 3);
i2c_led_send_pur_pdr(drvid, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
}
DBGC(DC_I2C3733_INIT_DRIVERS_COMPLETE);
@@ -357,12 +352,24 @@ void I2C3733_Control_Set(uint8_t state)
{
DBGC(DC_I2C3733_CONTROL_SET_BEGIN);
if (sr_exp_data.bit.SDB_N == 0 && state == 1)
{
gcr_actual = 0; //Set low GCR when turning on to prevent instant overload conditions
}
sr_exp_data.bit.SDB_N = (state == 1 ? 1 : 0);
SR_EXP_WriteData();
DBGC(DC_I2C3733_CONTROL_SET_COMPLETE);
}
//Return 1 if enabled
//Return 0 if disabled
uint8_t I2C3733_Control_Get(void)
{
return (sr_exp_data.bit.SDB_N == 1);
}
void i2c_led_desc_defaults(void)
{
dmac_desc.BTCTRL.bit.STEPSIZE = 0; //SRCINC used in favor for auto 1 inc
@@ -421,7 +428,6 @@ void i2c_led_send_GCR_dma(uint8_t drvid)
void i2c_led_send_pwm_dma(uint8_t drvid)
{
//Note: This copies the CURRENT pwm buffer, which may be getting modified
memcpy(dma_sendbuf, issidrv[drvid].pwm, ISSI3733_PG1_BYTES);
*dma_sendbuf = 0; //Force start location offset to zero
i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG1_BYTES);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -32,6 +32,7 @@ DmacDescriptor dmac_desc_wb;
uint8_t I2C3733_Init_Control(void);
uint8_t I2C3733_Init_Drivers(void);
void I2C3733_Control_Set(uint8_t state);
uint8_t I2C3733_Control_Get(void);
void I2C_DMAC_LED_Init(void);
#define I2C_Q_SIZE 100

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -62,120 +62,123 @@ issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
issi3733_led_t led_map[ISSI3733_LED_COUNT] = ISSI3733_LED_MAP;
RGB led_buffer[ISSI3733_LED_COUNT];
uint8_t gcr_desired;
uint8_t gcr_actual;
uint8_t gcr_actual_last;
uint8_t gcr_desired; //User's desired GCR value (brightness setting)
uint8_t gcr_actual; //The GCR value about to be written to LED drivers
uint8_t gcr_actual_last; //The GCR value last written to LED drivers
#ifdef USE_MASSDROP_CONFIGURATOR
uint8_t gcr_breathe;
uint8_t gcr_breathe; //The maximum attained GCR value during a breathe cycle (for smooth light transitions)
float breathe_mult;
float pomod;
#endif
uint32_t power_sum = 0; //Sum of RGB values for current LED pattern (about to be visible)
uint32_t power_sum_last; //Sum of RGB values for previous LED pattern (currently visible)
#endif // USE_MASSDROP_CONFIGURATOR
#define ACT_GCR_NONE 0
#define ACT_GCR_INC 1
#define ACT_GCR_DEC 2
//Actions to take for GCR
#define ACT_GCR_NONE 0 //Take no action on GCR
#define ACT_GCR_INC 1 //Increase GCR
#define ACT_GCR_DEC 2 //Decrease GCR
#define LED_GCR_STEP_AUTO 2
//GCR step settings
#define LED_GCR_STEP_AUTO 1 //How many GCR steps to take per increase or decrease call
#define ACT_GCR_DEC_COUNT -1 //Number at which a GCR decrease will actually happen (decrements should happen fast to react to sudden high load)
#define ACT_GCR_INC_COUNT 5 //Number at which a GCR increase will actually happen (increments should happen slow to gently approach power limits)
static uint8_t gcr_min_counter;
static uint8_t v_5v_cat_hit;
int8_t gcr_change_counter; //GCR increase and decrease calls are counted here and acted upon when a count limit is hit
uint16_t v_5v_cat_hit; //Flag for when 5v catastrophic level has been reached, and timer for recovery period
uint64_t v_5v_low_timer; //Timer for disabling USB extra device after causing a low voltage situation for an amount of time (-1 indicates timer not active)
//WARNING: Automatic GCR is in place to prevent USB shutdown and LED driver overloading
//Note: GCR updates are currently synced to come before a PWM update, so GCR updates actually happen off the PWM update timer
void gcr_compute(void)
{
uint8_t action = ACT_GCR_NONE;
uint8_t gcr_use = gcr_desired;
uint8_t action = ACT_GCR_NONE; //Default GCR action to be taken
uint8_t gcr_use = gcr_desired; //The GCR value to test against
if (!I2C3733_Control_Get()) //If LED drivers are not on
{
gcr_actual = 0; //Minimize GCR
return; //Nothing else to do
}
#ifdef USE_MASSDROP_CONFIGURATOR
if (led_animation_breathing)
if (led_animation_breathing) //If breathing effect is being used
{
gcr_use = gcr_breathe;
gcr_use = gcr_breathe; //Set max GCR possible to the highest GCR attained during breathe cycles
}
#endif
#endif // USE_MASSDROP_CONFIGURATOR
//If the 5v takes a catastrophic hit, disable the LED drivers briefly, assert auto gcr mode, min gcr and let the auto take over
if (v_5v < V5_CAT)
if (usb_gcr_auto) //If automatic GCR is enabled
{
I2C3733_Control_Set(0);
//CDC_print("USB: WARNING: 5V catastrophic level reached! Disabling LED drivers!\r\n"); //Blocking print is bad here!
v_5v_cat_hit = 20; //~100ms recover
gcr_actual = 0; //Minimize GCR
usb_gcr_auto = 1; //Force auto mode enabled
return;
//If 5v bus is low or the desired GCR is less than actual, and we have not reached the decrease threshold
if ((uint16_t)g_v_5v_avg < V5_LOW || gcr_desired < gcr_actual)
{
if (gcr_change_counter > ACT_GCR_DEC_COUNT)
{
gcr_change_counter--; //Decrease GCR change count
}
}
else if ((uint16_t)g_v_5v_avg > V5_HIGH) //else if 5v bus is high and we have not reached the increase threshold
{
if (gcr_change_counter < ACT_GCR_INC_COUNT)
{
gcr_change_counter++; //Increase GCR change count
}
}
else
{
//If no action, seek zero
if (gcr_change_counter > 0) { gcr_change_counter--; }
else if (gcr_change_counter < 0) { gcr_change_counter++; }
}
if (gcr_change_counter == ACT_GCR_DEC_COUNT) //If change counter has reached the decrease threshold
{
//Note: Not checking if there is room to decrease here as that is taken into account differently on the actual decrease action
action = ACT_GCR_DEC; //Set action to decrease
}
else if (gcr_change_counter == ACT_GCR_INC_COUNT) //Else if change counter has reached the increase threshold
{
if (gcr_actual < gcr_use && I2C3733_Control_Get()) //If there is room to increase and LED drivers are on
{
action = ACT_GCR_INC; //Set action to increase
}
}
}
else if (v_5v_cat_hit > 1)
else //Else automatic GCR is disabled so immediately follow user's desired value
{
v_5v_cat_hit--;
return;
}
else if (v_5v_cat_hit == 1)
{
I2C3733_Control_Set(1);
CDC_print("USB: WARNING: Re-enabling LED drivers\r\n");
v_5v_cat_hit = 0;
return;
if (gcr_actual < gcr_use) action = ACT_GCR_INC; //If actual has not met the use value, set action to increase
else if (gcr_actual > gcr_use) action = ACT_GCR_DEC; //Else if the actual is more than the use value, set action to decrease
}
if (usb_gcr_auto)
{
if (v_5v_avg < V5_LOW) action = ACT_GCR_DEC;
else if (v_5v_avg > V5_HIGH && gcr_actual < gcr_use) action = ACT_GCR_INC;
else if (gcr_actual > gcr_use) action = ACT_GCR_DEC;
}
else
{
if (gcr_actual < gcr_use) action = ACT_GCR_INC;
else if (gcr_actual > gcr_use) action = ACT_GCR_DEC;
}
if (action == ACT_GCR_NONE)
{
gcr_min_counter = 0;
}
else if (action == ACT_GCR_INC)
if (action == ACT_GCR_INC)
{
gcr_change_counter = 0;
if (LED_GCR_STEP_AUTO > LED_GCR_MAX - gcr_actual) gcr_actual = LED_GCR_MAX; //Obey max and prevent wrapping
else gcr_actual += LED_GCR_STEP_AUTO;
gcr_min_counter = 0;
}
else if (action == ACT_GCR_DEC)
{
gcr_change_counter = 0;
if (LED_GCR_STEP_AUTO > gcr_actual) //Prevent wrapping
{
gcr_actual = 0;
//At this point, power can no longer be cut from the LED drivers, so focus on cutting out extra port if active
if (usb_extra_state != USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) //If not in a wait for replug state
{
if (usb_extra_state == USB_EXTRA_STATE_ENABLED) //If extra usb is enabled
{
gcr_min_counter++;
if (gcr_min_counter > 200) //5ms per check = 1s delay
{
USB_ExtraSetState(USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG);
usb_extra_manual = 0; //Force disable manual mode of extra port
if (usb_extra_manual) CDC_print("USB: Disabling extra port until replug and manual mode toggle!\r\n");
else CDC_print("USB: Disabling extra port until replug!\r\n");
}
}
}
}
else
{
//Power successfully cut back from LED drivers
gcr_actual -= LED_GCR_STEP_AUTO;
gcr_min_counter = 0;
#ifdef USE_MASSDROP_CONFIGURATOR
//If breathe mode is active, the top end can fluctuate if the host can not supply enough current
//So set the breathe GCR to where it becomes stable
//So set the breathe GCR to where it can safely reach
if (led_animation_breathing == 1)
{
gcr_breathe = gcr_actual;
//PS: At this point, setting breathing to exhale makes a noticebly shorter cycle
// and the same would happen maybe one or two more times. Therefore I'm favoring
// powering through one full breathe and letting gcr settle completely
// powering through one full breathe and letting GCR settle completely
}
#endif
#endif // USE_MASSDROP_CONFIGURATOR
}
}
}
@@ -227,7 +230,7 @@ void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b)
led_buffer[i].r = r;
led_buffer[i].g = g;
led_buffer[i].b = b;
#endif
#endif // USE_MASSDROP_CONFIGURATOR
}
}
@@ -247,7 +250,7 @@ void init(void)
led_matrix_prepare();
gcr_min_counter = 0;
gcr_change_counter = 0;
v_5v_cat_hit = 0;
DBGC(DC_LED_MATRIX_INIT_COMPLETE);
@@ -255,16 +258,34 @@ void init(void)
void flush(void)
{
#ifdef USE_MASSDROP_CONFIGURATOR
if (!led_enabled) { return; } //Prevent calculations and I2C traffic if LED drivers are not enabled
#else
if (!sr_exp_data.bit.SDB_N) { return; } //Prevent calculations and I2C traffic if LED drivers are not enabled
#endif
uint8_t drvid;
// Wait for previous transfer to complete
#ifdef USE_MASSDROP_CONFIGURATOR
//If there will be a sudden spike in required power, lower GCR prior to change according to some ratio
if (power_sum > (uint32_t)((float)power_sum_last * 1.5))
{
//Lower GCR according to a percentage of the change in power ratio
gcr_actual = (uint8_t)((((float)gcr_actual * ((float)power_sum_last / (float)power_sum)) * 0.8) + 0.5);
}
power_sum_last = power_sum;
power_sum = 0;
//NOTE: Allow GCR updates even if the drivers lighting is disabled
if (gcr_actual != gcr_actual_last)
{
for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++) { I2C_LED_Q_GCR(drvid); } //Queue data
gcr_actual_last = gcr_actual;
if (!I2C3733_Control_Get()) { i2c_led_q_run(); } //Run the queue if we know flush will not complete due to drivers being disabled
}
#endif // USE_MASSDROP_CONFIGURATOR
if (!I2C3733_Control_Get()) { return; } //Prevent calculations and I2C traffic if LED drivers are not enabled
//Wait for previous transfer to complete
//If timings are proper, we should never get into this busy wait state
while (i2c_led_q_running) {}
// Copy buffer to live DMA region
//Copy buffer to live DMA region
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++)
{
*led_map[i].rgb.r = led_buffer[i].r;
@@ -272,47 +293,35 @@ void flush(void)
*led_map[i].rgb.b = led_buffer[i].b;
}
#ifdef USE_MASSDROP_CONFIGURATOR
breathe_mult = 1;
for (drvid = 0; drvid < ISSI3733_DRIVER_COUNT; drvid++) { I2C_LED_Q_PWM(drvid); } //Queue data
i2c_led_q_run();
//Perform any once-per-frame calculations or setup here
#ifdef USE_MASSDROP_CONFIGURATOR
if (led_animation_breathing)
{
//+60us 119 LED
led_animation_breathe_cur += BREATHE_STEP * breathe_dir;
if (led_animation_breathe_cur >= BREATHE_MAX_STEP)
breathe_dir = -1;
else if (led_animation_breathe_cur <= BREATHE_MIN_STEP)
breathe_dir = 1;
if (led_animation_breathe_cur >= BREATHE_MAX_STEP) { breathe_dir = -1; }
else if (led_animation_breathe_cur <= BREATHE_MIN_STEP) { breathe_dir = 1; }
//Brightness curve created for 256 steps, 0 - ~98%
breathe_mult = 0.000015 * led_animation_breathe_cur * led_animation_breathe_cur;
if (breathe_mult > 1) breathe_mult = 1;
else if (breathe_mult < 0) breathe_mult = 0;
if (breathe_mult > 1) { breathe_mult = 1; }
else if (breathe_mult < 0) { breathe_mult = 0; }
}
//This should only be performed once per frame
pomod = (float)((g_rgb_counters.tick / 10) % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
pomod = 0;
if (led_animation_speed != 0) //Avoid DIV0
{
pomod = (float)((g_rgb_counters.tick / 10) % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
}
pomod *= 100.0f;
pomod = (uint32_t)pomod % 10000;
pomod /= 100.0f;
#endif // USE_MASSDROP_CONFIGURATOR
uint8_t drvid;
//NOTE: GCR does not need to be timed with LED processing, but there is really no harm
if (gcr_actual != gcr_actual_last)
{
for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
I2C_LED_Q_GCR(drvid); //Queue data
gcr_actual_last = gcr_actual;
}
for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
I2C_LED_Q_PWM(drvid); //Queue data
i2c_led_q_run();
}
void led_matrix_indicators(void)
@@ -340,9 +349,16 @@ void led_matrix_indicators(void)
#endif //KANA
(0))
{
led_buffer[i].r = 255 - led_buffer[i].r;
led_buffer[i].g = 255 - led_buffer[i].g;
led_buffer[i].b = 255 - led_buffer[i].b;
led_buffer[i].r = 255 - led_buffer[i].r; //TODO: Issue here with keeping the LED lit, static value works
led_buffer[i].g = 255 - led_buffer[i].g; //TODO: Issue here with keeping the LED lit, static value works
led_buffer[i].b = 255 - led_buffer[i].b; //TODO: Issue here with keeping the LED lit, static value works
//TODO: Old code, see if this hard cutoff is better// if (*led_cur->rgb.r > 127) *led_cur->rgb.r = 0;
//TODO: Old code, see if this hard cutoff is better// else *led_cur->rgb.r = 255;
//TODO: Old code, see if this hard cutoff is better// if (*led_cur->rgb.g > 127) *led_cur->rgb.g = 0;
//TODO: Old code, see if this hard cutoff is better// else *led_cur->rgb.g = 255;
//TODO: Old code, see if this hard cutoff is better// if (*led_cur->rgb.b > 127) *led_cur->rgb.b = 0;
//TODO: Old code, see if this hard cutoff is better// else *led_cur->rgb.b = 255;
}
}
}
@@ -370,15 +386,31 @@ uint8_t led_animation_breathing = 0;
uint8_t led_animation_id = 0;
float led_animation_speed = 4.0f;
uint8_t led_lighting_mode = LED_MODE_NORMAL;
uint8_t led_enabled = 1;
uint8_t led_animation_breathe_cur = BREATHE_MIN_STEP;
uint8_t breathe_dir = 1;
uint8_t led_animation_circular = 0;
float led_edge_brightness = 1.0f;
uint8_t led_edge_mode = LED_EDGE_MODE_ALL;
static void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo, float pos) {
float po;
while (f->end != 1)
{
//OLD-CODE// //TODO: Get this working again if (led_animation_circular) {
//OLD-CODE// //TODO: Get this working again po = sqrtf((powf(fabsf((disp.width / 2) - (led_cur->x - disp.left)), 2) + powf(fabsf((disp.height / 2) - (led_cur->y - disp.bottom)), 2))) / disp.max_distance * 100;
//OLD-CODE// //TODO: Get this working again }
//OLD-CODE// //TODO: Get this working again else {
//OLD-CODE// //TODO: Get this working again if (led_animation_orientation)
//OLD-CODE// //TODO: Get this working again {
//OLD-CODE// //TODO: Get this working again po = led_cur->py;
//OLD-CODE// //TODO: Get this working again }
//OLD-CODE// //TODO: Get this working again else
//OLD-CODE// //TODO: Get this working again {
//OLD-CODE// //TODO: Get this working again po = led_cur->px;
//OLD-CODE// //TODO: Get this working again }
//OLD-CODE// //TODO: Get this working again }
po = pos; //Reset po for new frame
//Add in any moving effects
@@ -429,22 +461,62 @@ static void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo, flo
}
}
//TODO: For circular animation fix?// void disp_calc_extents(void)
//TODO: For circular animation fix?// {
//TODO: For circular animation fix?// issi3733_led_t *cur = led_map;
//TODO: For circular animation fix?//
//TODO: For circular animation fix?// disp.left = 1e10;
//TODO: For circular animation fix?// disp.right = -1e10;
//TODO: For circular animation fix?// disp.top = -1e10;
//TODO: For circular animation fix?// disp.bottom = 1e10;
//TODO: For circular animation fix?//
//TODO: For circular animation fix?// while (cur < lede)
//TODO: For circular animation fix?// {
//TODO: For circular animation fix?// if (cur->x < disp.left) disp.left = cur->x;
//TODO: For circular animation fix?// if (cur->x > disp.right) disp.right = cur->x;
//TODO: For circular animation fix?// if (cur->y < disp.bottom) disp.bottom = cur->y;
//TODO: For circular animation fix?// if (cur->y > disp.top) disp.top = cur->y;
//TODO: For circular animation fix?//
//TODO: For circular animation fix?// cur++;
//TODO: For circular animation fix?// }
//TODO: For circular animation fix?//
//TODO: For circular animation fix?// disp.width = disp.right - disp.left;
//TODO: For circular animation fix?// disp.height = disp.top - disp.bottom;
//TODO: For circular animation fix?// disp.max_distance = sqrtf(powf(disp.width, 2) + powf(disp.height, 2));
//TODO: For circular animation fix?// }
#define RGB_MAX_DISTANCE 232.9635f
static void led_matrix_massdrop_config_override(int i)
{
float ro = 0;
float go = 0;
float bo = 0;
float po = (led_animation_orientation)
? (float)g_led_config.point[i].y / 64.f * 100
: (float)g_led_config.point[i].x / 224.f * 100;
float po;
uint8_t highest_active_layer = biton32(layer_state);
if (led_animation_circular) {
po = sqrtf((powf(fabsf((224 / 2) - (float)g_led_config.point[i].x), 2) + powf(fabsf((64 / 2) - (float)g_led_config.point[i].y), 2))) / RGB_MAX_DISTANCE * 100;
} else {
if (led_animation_orientation) {
po = (float)g_led_config.point[i].y / 64.f * 100;
} else {
po = (float)g_led_config.point[i].x / 224.f * 100;
}
}
if (led_lighting_mode == LED_MODE_KEYS_ONLY && LED_IS_EDGE(led_map[i].scan)) {
//Do not act on this LED
} else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && !LED_IS_EDGE(led_map[i].scan)) {
// TODO: sort this out
/*
if (led_lighting_mode == LED_MODE_KEYS_ONLY && HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {
//Do not act on this LED
} else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && !HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {
*/
//Do not act on this LED
} else if (led_edge_mode == LED_EDGE_MODE_ALTERNATE && LED_IS_EDGE_ALT(led_map[i].scan)) {
//Do not act on this LED (Edge alternate lighting mode)
} else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY) {
//Do not act on this LED (Only show indicators)
} else {
@@ -480,6 +552,7 @@ static void led_matrix_massdrop_config_override(int i)
led_cur_instruction++;
}
//Clamp values 0-255
if (ro > 255) ro = 255; else if (ro < 0) ro = 0;
if (go > 255) go = 255; else if (go < 0) go = 0;
if (bo > 255) bo = 255; else if (bo < 0) bo = 0;
@@ -492,9 +565,19 @@ static void led_matrix_massdrop_config_override(int i)
}
}
//Adjust edge LED brightness
if (led_edge_brightness != 1 && LED_IS_EDGE(led_map[i].scan))
{
ro *= led_edge_brightness;
go *= led_edge_brightness;
bo *= led_edge_brightness;
}
led_buffer[i].r = (uint8_t)ro;
led_buffer[i].g = (uint8_t)go;
led_buffer[i].b = (uint8_t)bo;
power_sum += (uint8_t)ro + (uint8_t)go + (uint8_t)bo;
}
#endif // USE_MASSDROP_CONFIGURATOR

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -47,7 +47,7 @@ typedef struct issi3733_driver_s {
uint8_t onoff[ISSI3733_PG_ONOFF_BYTES]; //PG0 - LED Control Register - LED On/Off Register
uint8_t open[ISSI3733_PG_OR_BYTES]; //PG0 - LED Control Register - LED Open Register
uint8_t shrt[ISSI3733_PG_SR_BYTES]; //PG0 - LED Control Register - LED Short Register
uint8_t pwm[ISSI3733_PG_PWM_BYTES]; //PG1 - PWM Register
uint8_t pwm[ISSI3733_PG_PWM_BYTES]; //PG1 - PWM Register for working data
uint8_t abm[ISSI3733_PG_ABM_BYTES]; //PG2 - Auto Breath Mode Register
uint8_t conf[ISSI3733_PG_FN_BYTES]; //PG3 - Function Register
} issi3733_driver_t;
@@ -142,16 +142,30 @@ extern uint8_t led_animation_breathing;
extern uint8_t led_animation_id;
extern float led_animation_speed;
extern uint8_t led_lighting_mode;
extern uint8_t led_enabled;
extern uint8_t led_animation_breathe_cur;
extern uint8_t led_animation_direction;
extern uint8_t breathe_dir;
extern uint8_t led_animation_orientation;
extern uint8_t led_animation_circular;
extern float led_edge_brightness;
extern uint8_t led_edge_mode;
#define LED_MODE_NORMAL 0 //Must be 0
#define LED_MODE_NORMAL 0 //Must be 0
#define LED_MODE_KEYS_ONLY 1
#define LED_MODE_NON_KEYS_ONLY 2
#define LED_MODE_INDICATORS_ONLY 3
#define LED_MODE_MAX_INDEX LED_MODE_INDICATORS_ONLY //Must be highest value
#define LED_MODE_MAX_INDEX LED_MODE_INDICATORS_ONLY //Must be highest valued LED mode
#define LED_EDGE_MODE_ALL 0 //All edge LEDs are active (Must be 0)
#define LED_EDGE_MODE_ALTERNATE 1 //Alternate mode of edge LEDs are active (Intention is for 'only every other edge LED' to be active)
#define LED_EDGE_MODE_MAX LED_EDGE_MODE_ALTERNATE //Must be the highest valued LED edge mode
#define LED_EDGE_FULL_MODE 255 //LEDs configured with this scan code will always be on for edge lighting modes
#define LED_EDGE_ALT_MODE 254 //LEDs configured with this scan code will turn off in edge alternating mode
#define LED_EDGE_MIN_SCAN 254 //LEDs configured with scan code >= to this are assigned as edge LEDs
#define LED_IS_EDGE(scan) (scan >= LED_EDGE_MIN_SCAN) //Return true if an LED's scan value indicates an edge LED
#define LED_IS_EDGE_ALT(scan) (scan == LED_EDGE_ALT_MODE) //Return true if an LED's scan value indicates an alternate edge mode LED
#endif // USE_MASSDROP_CONFIGURATOR

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -31,6 +31,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//From keyboard's directory
#include "config_led.h"
volatile char embed_version[] = COMPILE_VERSION;
uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; //Saved USB state from hardware value to detect changes
void main_subtasks(void);
@@ -188,9 +190,9 @@ void main_subtask_usb_state(void)
{
if (fsmstate_on_delay == 0) //If ON delay timer is cleared
{
fsmstate_on_delay = timer_read64() + 250; //Set ON delay timer
fsmstate_on_delay = timer_read64() + 250; //Set ON delay timer
}
else if (timer_read64() > fsmstate_on_delay) //Else if ON delay timer is active and timed out
else if (timer_read64() > fsmstate_on_delay) //Else if ON delay timer is active and timed out
{
suspend_wakeup_init(); //Run wakeup routine
g_usb_state = fsmstate_now; //Save current USB state
@@ -207,12 +209,14 @@ void main_subtask_power_check(void)
{
static uint64_t next_5v_checkup = 0;
if (timer_read64() > next_5v_checkup)
if (timer_read64() >= next_5v_checkup)
{
next_5v_checkup = timer_read64() + 5;
next_5v_checkup = timer_read64() + POWER_CHECK_INTERVAL;
v_5v = adc_get(ADC_5V);
v_5v_avg = 0.9 * v_5v_avg + 0.1 * v_5v;
g_v_5v = adc_get(ADC_5V);
g_v_5v_avg = (((float)V_5V_AVGS - 1) / (float)V_5V_AVGS) * g_v_5v_avg + (1 / (float)V_5V_AVGS) * (float)g_v_5v;
power_run(); //Check up on 5v bus voltage for spikes or low conditions
#ifdef RGB_MATRIX_ENABLE
gcr_compute();
@@ -224,9 +228,9 @@ void main_subtask_usb_extra_device(void)
{
static uint64_t next_usb_checkup = 0;
if (timer_read64() > next_usb_checkup)
if (timer_read64() >= next_usb_checkup)
{
next_usb_checkup = timer_read64() + 10;
next_usb_checkup = timer_read64() + USBC_CFG_PERIOD;
USB_HandleExtraDevice();
}
@@ -253,13 +257,14 @@ int main(void)
CLK_init();
ADC0_init();
ADC_init();
SR_EXP_Init();
#ifdef RGB_MATRIX_ENABLE
i2c1_init();
#endif // RGB_MATRIX_ENABLE
power_init();
matrix_init();
@@ -299,10 +304,10 @@ int main(void)
uint64_t next_print = 0;
#endif //CONSOLE_ENABLE
v_5v_avg = adc_get(ADC_5V);
debug_code_disable();
usbc_enable();
while (1)
{
main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals
@@ -323,14 +328,25 @@ int main(void)
#ifdef CONSOLE_ENABLE
if (timer_read64() > next_print)
{
next_print = timer_read64() + 250;
next_print = timer_read64() + 1;
//Add any debug information here that you want to see very often
//dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired);
//Corrected CC values for host port detection debugging
//dprintf("%4u %4u %4u %4u\n",ADC_CC_5VCOR(g_v_5v, adc_get(ADC_C1A5)),
// ADC_CC_5VCOR(g_v_5v, adc_get(ADC_C1B5)),
// ADC_CC_5VCOR(g_v_5v, adc_get(ADC_C2A5)),
// ADC_CC_5VCOR(g_v_5v, adc_get(ADC_C2B5)));
//USB state and CC line monitoring
//dprintf("%4u %4u %4u %4u %2u %1u\n",usbc_cc_a5_v,usbc_cc_b5_v,(uint16_t)usbc_cc_a5_v_avg,(uint16_t)usbc_cc_b5_v_avg,usbc.state,usbc.state == USB_STATE_ATTACHED_SRC ? 1 : 0);
//Power manager monitoring
//dprintf("%4u %4u %3u %3u %3u %i %3u\n",g_v_5v,(uint16_t)g_v_5v_avg,gcr_desired,(uint8_t)gcr_actual,gcr_actual_last,gcr_change_counter,usbc.state);
}
#endif //CONSOLE_ENABLE
}
return 1;
}

View File

@@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef _MAIN_ARM_ATSAM_H_
#define _MAIN_ARM_ATSAM_H_
#define COMPILE_VERSION "VER "__DATE__" "__TIME__" [" QMK_KEYBOARD ":" QMK_KEYMAP "]\n\r"
uint8_t keyboard_leds(void);
#endif //_MAIN_ARM_ATSAM_H_

View File

@@ -1,5 +1,4 @@
#ifndef _MD_BOOTLOADER_H_
#define _MD_BOOTLOADER_H_
#pragma once
extern uint32_t _srom;
extern uint32_t _lrom;
@@ -13,12 +12,3 @@ extern uint32_t _eram;
#define BOOTLOADER_MAGIC 0x3B9ACA00
#define MAGIC_ADDR (uint32_t *)((intptr_t)(&_eram) - 4)
#endif
#ifdef MD_BOOTLOADER
#define MCU_HZ 48000000
#define I2C_HZ 0 //Not used
#endif //MD_BOOTLOADER
#endif //_MD_BOOTLOADER_H_

View File

@@ -0,0 +1,100 @@
/*
Copyright 2019 Massdrop Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MD_BOOTLOADER
#include "arm_atsam_protocol.h"
uint64_t v_5v_cat_timer; //Timer for recovery period post 5v catastrophic low voltage detected (and LED driver disable)(-1 indicates timer not active)
uint64_t v_5v_low_timer; //Timer for disabling USB extra device after causing a low voltage situation for an amount of time (-1 indicates timer not active)
//Returns 1 if the 5v bus is in a catastrophic low voltage condition
//Returns 0 if the 5v bus is OK
uint8_t power_5v_check(void) {
if (g_v_5v < V5_CAT) { //If the 5v bus has reached a catastrophic low level
//See if this is a spike condition due to noise by re-testing a few times
uint8_t v_5v_tests; //Current 5v bus test number
uint16_t v_5v_test_cat; //Current 5v bus reading
for (v_5v_tests = 0; v_5v_tests < POWER_5V_SPIKE_TESTS; v_5v_tests++) { //Run spike tests
v_5v_test_cat = adc_get(ADC_5V); //Get new 5v bus reading
if (v_5v_test_cat > V5_CAT) { //If the reading is not catastrophic
g_v_5v = v_5v_test_cat; //Spike was temporary so update to new reading
break; //Break from spike testing
}
}
}
if (g_v_5v < V5_CAT) {
//The spike is a sustained event, so begin cutting back power where possible to recover
//If the LED drivers are on, disable them briefly, set GCR to minimum, and assert auto GCR mode is enabled
if (I2C3733_Control_Get()) {
I2C3733_Control_Set(0); //Disable all LED drivers
v_5v_cat_timer = timer_read64() + 250; //Begin the catastrophic low voltage timer
gcr_actual = 0; //Minimize GCR
usb_gcr_auto = 1; //Force auto GCR mode enabled
dprintf("USB: WARNING: 5V catastrophic level reached! Disabling LED drivers!\n"); //Debug output
} else { //Else the LED drivers are already disabled or at zero GCR, so the extra port is taking too much power, cut its 5v
if (usbc.state == USB_STATE_ATTACHED_SRC) { //If a device is attached
if (usbc.state != USB_STATE_DISABLED_UNTIL_DETACH) { //If not already in disabled waiting state
usbc.state = USB_STATE_DISABLED_UNTIL_DETACH; //Set state to disable until the device is unplugged
usbc_task(); //Immediately update USBC state to disable 5V
dprintf("USB: Disabling extra port until device unplugged!\n"); //Debug output
}
}
}
}
if (((uint16_t)g_v_5v_avg < V5_LOW) && (usbc.state == USB_STATE_ATTACHED_SRC)) //If 5v bus is low and a USB device is attached
{
if (v_5v_low_timer == -1) { //If the low voltage timer is not already running
v_5v_low_timer = timer_read64() + 1000; //Set the low voltage timer for 1s
}
if (timer_read64() > v_5v_low_timer) { //If the low voltage timer has expired
usbc.state = USB_STATE_DISABLED_UNTIL_DETACH; //Set usbc state to remove the load
usbc_task(); //Immediately update USBC state to disable 5V
dprintf("USB: Disabling extra port until device unplugged!\n"); //Debug output
v_5v_low_timer = -1; //Disable the low voltage timer
}
} else { //else 5v bus is not low or USB device is not attached
v_5v_low_timer = -1; //Disable the low voltage timer
}
if (v_5v_cat_timer != -1) { //If the catastrophic timer is active
if (timer_read64() > v_5v_cat_timer) { //If the catastrophic timer has expired
if (!I2C3733_Control_Get()) { //If LED drivers are enabled by the user
I2C3733_Control_Set(1); //Re-enable the LED drivers
}
dprintf("USB: WARNING: Re-enabling LED drivers\n"); //Debug output
v_5v_cat_timer = -1; //Disable the timer
} else { //Else the catastrophic timer is still running
return 1; //Return catastrophic state
}
}
return 0; //Return OK state
}
void power_init(void) {
v_5v_cat_timer = -1; //Disable the catastrophic low voltage timer
v_5v_low_timer = -1; //Disable the low voltage timer
}
void power_run(void) {
power_5v_check(); //Run 5v bus check
}
#endif //MD_BOOTLOADER

View File

@@ -0,0 +1,24 @@
/*
Copyright 2019 Massdrop Inc.
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
#define POWER_5V_SPIKE_TESTS 3 //Number of tests to do when a catastrophic spike is detected, to determine if it is a sustained event
uint8_t power_5v_check(void);
void power_init(void);
void power_run(void);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -17,71 +17,114 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "arm_atsam_protocol.h"
/* Shift Register output EXPander Data */
sr_exp_t sr_exp_data;
/* Shift Register output EXPander Write Data */
void SR_EXP_WriteData(void)
{
SR_EXP_RCLK_LO;
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.DRE)) { DBGC(DC_SPI_WRITE_DRE); }
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.DRE)) { DBGC(DC_SPI_EXP_WRITE_DRE); }
SR_EXP_SERCOM->SPI.DATA.bit.DATA = sr_exp_data.reg & 0xFF; //Shift in bits 7-0
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { DBGC(DC_SPI_WRITE_TXC_1); }
/* Shift in bits 7 - 0 */
SR_EXP_SERCOM->SPI.DATA.bit.DATA = sr_exp_data.reg & 0xFF;
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { DBGC(DC_SPI_EXP_WRITE_TXC_1); }
SR_EXP_SERCOM->SPI.DATA.bit.DATA = (sr_exp_data.reg >> 8) & 0xFF; //Shift in bits 15-8
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { DBGC(DC_SPI_WRITE_TXC_2); }
/* Shift in bits 15 - 8 */
SR_EXP_SERCOM->SPI.DATA.bit.DATA = (sr_exp_data.reg >> 8) & 0xFF;
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { DBGC(DC_SPI_EXP_WRITE_TXC_2); }
SR_EXP_RCLK_HI;
}
/* Shift Register output EXPander Initialization */
void SR_EXP_Init(void)
{
DBGC(DC_SPI_INIT_BEGIN);
DBGC(DC_SPI_EXP_INIT_BEGIN);
CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
CLK_set_spi_freq(CHAN_SERCOM_SPI_EXP, FREQ_SPI_DEFAULT);
//Set up MCU Shift Register pins
/* Set up MCU shift register pins */
PORT->Group[SR_EXP_RCLK_PORT].DIRSET.reg = (1 << SR_EXP_RCLK_PIN);
PORT->Group[SR_EXP_OE_N_PORT].DIRSET.reg = (1 << SR_EXP_OE_N_PIN);
//Set up MCU SPI pins
/* Set up MCU SPI pins */
PORT->Group[SR_EXP_DATAOUT_PORT].PMUX[SR_EXP_DATAOUT_PIN / 2].bit.SR_EXP_DATAOUT_MUX_SEL = SR_EXP_DATAOUT_MUX; //MUX select for sercom
PORT->Group[SR_EXP_SCLK_PORT].PMUX[SR_EXP_SCLK_PIN / 2].bit.SR_EXP_SCLK_MUX_SEL = SR_EXP_SCLK_MUX; //MUX select for sercom
PORT->Group[SR_EXP_DATAOUT_PORT].PINCFG[SR_EXP_DATAOUT_PIN].bit.PMUXEN = 1; //MUX Enable
PORT->Group[SR_EXP_SCLK_PORT].PINCFG[SR_EXP_SCLK_PIN].bit.PMUXEN = 1; //MUX Enable
//Initialize Shift Register
SR_EXP_OE_N_DIS;
SR_EXP_RCLK_HI;
/* Run keyboard init routine to finalize initialization */
SR_EXP_Init_kb();
SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; //Data Order - LSB is transferred first
SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; //Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; //Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3; //Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; //Data Output PAD[0], Serial Clock PAD[1]
SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; //Operating Mode - Master operation
SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; //Enable - Peripheral is enabled or being enabled
while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { DBGC(DC_SPI_SYNC_ENABLING); }
sr_exp_data.reg = 0;
sr_exp_data.bit.HUB_CONNECT = 0;
sr_exp_data.bit.HUB_RESET_N = 0;
sr_exp_data.bit.S_UP = 0;
sr_exp_data.bit.E_UP_N = 1;
sr_exp_data.bit.S_DN1 = 1;
sr_exp_data.bit.E_DN1_N = 1;
sr_exp_data.bit.E_VBUS_1 = 0;
sr_exp_data.bit.E_VBUS_2 = 0;
sr_exp_data.bit.SRC_1 = 1;
sr_exp_data.bit.SRC_2 = 1;
sr_exp_data.bit.IRST = 1;
sr_exp_data.bit.SDB_N = 0;
SR_EXP_WriteData();
//Enable Shift Register output
SR_EXP_OE_N_ENA;
DBGC(DC_SPI_INIT_COMPLETE);
DBGC(DC_SPI_EXP_INIT_COMPLETE);
}
#ifdef SR_KC_SERCOM_NUM
/* Shift Register Key matrix Column drive Data */
sr_kc_t sr_kc_data;
/* Shift Register Key matrix Column drive Write Data */
void SR_KC_WriteData(void)
{
SR_KC_RCLK_LO;
while (!(SR_KC_SERCOM->SPI.INTFLAG.bit.DRE)) { DBGC(DC_SPI_KC_WRITE_DRE); }
/* Shift in bits 8 - 15 */
SR_KC_SERCOM->SPI.DATA.bit.DATA = (sr_kc_data.reg >> 8) & 0xFF;
while (!(SR_KC_SERCOM->SPI.INTFLAG.bit.TXC)) { DBGC(DC_SPI_KC_WRITE_TXC_1); }
/* Shift in bits 0 - 7 */
SR_KC_SERCOM->SPI.DATA.bit.DATA = sr_kc_data.reg & 0xFF;
while (!(SR_KC_SERCOM->SPI.INTFLAG.bit.TXC)) { DBGC(DC_SPI_KC_WRITE_TXC_2); }
SR_KC_RCLK_HI;
}
/* Shift Register Key matrix Column drive Initialization */
void SR_KC_Init(void)
{
DBGC(DC_SPI_KC_INIT_BEGIN);
CLK_set_spi_freq(CHAN_SERCOM_SPI_KC, FREQ_SPI_KC_DEFAULT);
/* Set up MCU shift register pins */
PORT->Group[SR_KC_RCLK_PORT].DIRSET.reg = (1 << SR_KC_RCLK_PIN);
PORT->Group[SR_KC_OE_N_PORT].DIRSET.reg = (1 << SR_KC_OE_N_PIN);
/* Set up MCU SPI pins */
PORT->Group[SR_KC_DATAOUT_PORT].PMUX[SR_KC_DATAOUT_PIN / 2].bit.SR_KC_DATAOUT_MUX_SEL = SR_KC_DATAOUT_MUX; //MUX select for sercom
PORT->Group[SR_KC_SCLK_PORT].PMUX[SR_KC_SCLK_PIN / 2].bit.SR_KC_SCLK_MUX_SEL = SR_KC_SCLK_MUX; //MUX select for sercom
PORT->Group[SR_KC_DATAOUT_PORT].PINCFG[SR_KC_DATAOUT_PIN].bit.PMUXEN = 1; //MUX Enable
PORT->Group[SR_KC_SCLK_PORT].PINCFG[SR_KC_SCLK_PIN].bit.PMUXEN = 1; //MUX Enable
/* Initialize shift register */
SR_KC_OE_N_DIS;
SR_KC_RCLK_HI;
SR_KC_SERCOM->SPI.CTRLA.bit.DORD = 0; //Data Order - MSB is transferred first
SR_KC_SERCOM->SPI.CTRLA.bit.CPOL = 1; //Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
SR_KC_SERCOM->SPI.CTRLA.bit.CPHA = 1; //Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
SR_KC_SERCOM->SPI.CTRLA.bit.DIPO = 3; //Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
SR_KC_SERCOM->SPI.CTRLA.bit.DOPO = 0; //Data Output PAD[0], Serial Clock PAD[1]
SR_KC_SERCOM->SPI.CTRLA.bit.MODE = 3; //Operating Mode - Master operation
SR_KC_SERCOM->SPI.CTRLA.bit.ENABLE = 1; //Enable - Peripheral is enabled or being enabled
while (SR_KC_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { DBGC(DC_SPI_KC_SYNC_ENABLING); }
/* Set default shift register values */
sr_kc_data.reg = 0;
/* Write shift register data */
SR_KC_WriteData();
/* Enable shift register output */
SR_KC_OE_N_ENA;
DBGC(DC_SPI_KC_INIT_COMPLETE);
}
#endif //SR_KC_SERCOM

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -18,6 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef _SPI_H_
#define _SPI_H_
#include "config_spi.h"
/* Various macros for use in this header */
#define SPI_MACRO_CONCAT(str,var) str ## var
#define SPI_MACRO_EXPAND(str,var) SPI_MACRO_CONCAT(str,var)
/* Macros to define Shift Register macro (Ex: SERCOM2) */
#define SR_EXP_SERCOM SPI_MACRO_EXPAND(SERCOM,SR_EXP_SERCOM_NUM)
/* Macros to define Shift Register Peripheral ID (Ex: ID_SERCOM2) */
#define SR_EXP_SERCOM_PID SPI_MACRO_EXPAND(ID_SERCOM,SR_EXP_SERCOM_NUM)
/* Macros for Shift Register control */
#define SR_EXP_RCLK_LO PORT->Group[SR_EXP_RCLK_PORT].OUTCLR.reg = (1 << SR_EXP_RCLK_PIN)
#define SR_EXP_RCLK_HI PORT->Group[SR_EXP_RCLK_PORT].OUTSET.reg = (1 << SR_EXP_RCLK_PIN)
@@ -38,33 +50,72 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SR_EXP_SCLK_MUX_SEL PMUXO
#endif
/* Data structure to define Shift Register output expander hardware */
/* This structure gets shifted into registers LSB first */
typedef union {
struct {
uint16_t RSVD4:1; /*!< bit: 0 */
uint16_t RSVD3:1; /*!< bit: 1 */
uint16_t RSVD2:1; /*!< bit: 2 */
uint16_t RSVD1:1; /*!< bit: 3 */
uint16_t SDB_N:1; /*!< bit: 4 SHUTDOWN THE CHIP WHEN 0, RUN WHEN 1 */
uint16_t IRST:1; /*!< bit: 5 RESET THE IS3733 I2C WHEN 1, RUN WHEN 0 */
uint16_t SRC_2:1; /*!< bit: 6 ADVERTISE A SOURCE TO USBC-2 CC */
uint16_t SRC_1:1; /*!< bit: 7 ADVERTISE A SOURCE TO USBC-1 CC */
uint16_t E_VBUS_2:1; /*!< bit: 8 ENABLE 5V OUT TO USBC-2 WHEN 1 */
uint16_t E_VBUS_1:1; /*!< bit: 9 ENABLE 5V OUT TO USBC-1 WHEN 1 */
uint16_t E_DN1_N:1; /*!< bit: 10 ENABLE DN1 1:2 MUX WHEN 0 */
uint16_t S_DN1:1; /*!< bit: 11 SELECT DN1 PATH 0:USBC-1, 1:USBC-2 */
uint16_t E_UP_N:1; /*!< bit: 12 ENABLE SUP 1:2 MUX WHEN 0 */
uint16_t S_UP:1; /*!< bit: 13 SELECT UP PATH 0:USBC-1, 1:USBC-2 */
uint16_t HUB_RESET_N:1; /*!< bit: 14 RESET USB HUB WHEN 0, RUN WHEN 1 */
uint16_t HUB_CONNECT:1; /*!< bit: 15 SIGNAL VBUS CONNECT TO USB HUB WHEN 1 */
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} sr_exp_t;
//Note: sr_exp_t struct defined in keyboard's config_spi.h
extern sr_exp_t sr_exp_data;
void SR_EXP_WriteData(void);
void SR_EXP_Init(void);
void SR_EXP_Init_kb(void);
//For devices which use two shift registers for key matrix column drive
#ifdef SR_KC_SERCOM_NUM
/* Macros to define Shift Register macro (Ex: SERCOM4) */
#define SR_KC_SERCOM SPI_MACRO_EXPAND(SERCOM,SR_KC_SERCOM_NUM)
/* Macros to define Shift Register Peripheral ID (Ex: ID_SERCOM2) */
#define SR_KC_SERCOM_PID SPI_MACRO_EXPAND(ID_SERCOM,SR_KC_SERCOM_NUM)
/* Macros for Shift Register control */
#define SR_KC_RCLK_LO PORT->Group[SR_KC_RCLK_PORT].OUTCLR.reg = (1 << SR_KC_RCLK_PIN)
#define SR_KC_RCLK_HI PORT->Group[SR_KC_RCLK_PORT].OUTSET.reg = (1 << SR_KC_RCLK_PIN)
#define SR_KC_OE_N_ENA PORT->Group[SR_KC_OE_N_PORT].OUTCLR.reg = (1 << SR_KC_OE_N_PIN)
#define SR_KC_OE_N_DIS PORT->Group[SR_KC_OE_N_PORT].OUTSET.reg = (1 << SR_KC_OE_N_PIN)
/* Determine bits to set for mux selection */
#if SR_KC_DATAOUT_PIN % 2 == 0
#define SR_KC_DATAOUT_MUX_SEL PMUXE
#else
#define SR_KC_DATAOUT_MUX_SEL PMUXO
#endif
/* Determine bits to set for mux selection */
#if SR_KC_SCLK_PIN % 2 == 0
#define SR_KC_SCLK_MUX_SEL PMUXE
#else
#define SR_KC_SCLK_MUX_SEL PMUXO
#endif
/* Data structure to define Shift Register output for key matrix column drive */
/* This structure gets shifted into registers MSB first */
typedef union {
struct {
uint16_t KC1:1; /*!< bit: 0 Key matrix column 1 drive */
uint16_t KC2:1; /*!< bit: 1 Key matrix column 2 drive */
uint16_t KC3:1; /*!< bit: 2 Key matrix column 3 drive */
uint16_t KC4:1; /*!< bit: 3 Key matrix column 4 drive */
uint16_t KC5:1; /*!< bit: 4 Key matrix column 5 drive */
uint16_t KC6:1; /*!< bit: 5 Key matrix column 6 drive */
uint16_t KC7:1; /*!< bit: 6 Key matrix column 7 drive */
uint16_t KC8:1; /*!< bit: 7 Key matrix column 8 drive */
uint16_t KC9:1; /*!< bit: 8 Key matrix column 9 drive */
uint16_t KC10:1; /*!< bit: 9 Key matrix column 10 drive */
uint16_t KC11:1; /*!< bit: 10 Key matrix column 11 drive */
uint16_t KC12:1; /*!< bit: 11 Key matrix column 12 drive */
uint16_t KC13:1; /*!< bit: 12 Key matrix column 13 drive */
uint16_t KC14:1; /*!< bit: 13 Key matrix column 14 drive */
uint16_t KC15:1; /*!< bit: 14 Key matrix column 15 drive */
uint16_t KC16:1; /*!< bit: 15 Key matrix column 16 drive */
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} sr_kc_t;
extern sr_kc_t sr_kc_data;
void SR_KC_WriteData(void);
void SR_KC_Init(void);
#endif //SR_KC_SERCOM
#endif //_SPI_H_

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -36,28 +36,22 @@ const uint16_t SERNAME[BOOTLOADER_SERIAL_MAX_SIZE] = { 'M','D','H','U','B','B','
// space as needed and adjust BOOTLOADER_SERIAL_MAX_SIZE to match amount given
#endif //MD_BOOTLOADER
uint8_t usb_host_port;
uint8_t g_usb_host_port;
#ifndef MD_BOOTLOADER
uint8_t usb_extra_state;
uint8_t usb_extra_manual;
uint8_t usb_gcr_auto;
#endif //MD_BOOTLOADER
uint16_t adc_extra;
void USB_write2422_block(void)
{
void USB_write2422_block(void) {
unsigned char *dest = i2c0_buf;
unsigned char *src;
unsigned char *base = (unsigned char *)&USB2422_shadow;
DBGC(DC_USB_WRITE2422_BLOCK_BEGIN);
for (src = base; src < base + 256; src += 32)
{
for (src = base; src < base + 256; src += 32) {
dest[0] = src - base;
dest[1] = 32;
memcpy(&dest[2], src, 32);
@@ -70,8 +64,7 @@ void USB_write2422_block(void)
DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE);
}
void USB2422_init(void)
{
void USB2422_init(void) {
Gclk *pgclk = GCLK;
Mclk *pmclk = MCLK;
Port *pport = PORT;
@@ -80,7 +73,7 @@ void USB2422_init(void)
DBGC(DC_USB2422_INIT_BEGIN);
while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB2422_INIT_WAIT_5V_LOW); }
while (adc_get(ADC_5V) < ADC_5V_V2C(ADC_5V_START_LEVEL)) { DBGC(DC_USB2422_INIT_WAIT_5V_LOW); }
//setup peripheral and synchronous bus clocks to USB
pgclk->PCHCTRL[10].bit.GEN = 0;
@@ -131,15 +124,14 @@ void USB2422_init(void)
i2c0_init(); //IC2 clk must be high at USB2422 reset release time to signal SMB configuration
sr_exp_data.bit.HUB_CONNECT = 1; //connect signal
sr_exp_data.bit.HUB_RESET_N = 1; //reset high
sr_exp_data.bit.HUB_CONNECT = 1; //connect signal high to connect
sr_exp_data.bit.HUB_RESET_N = 1; //reset high to run
SR_EXP_WriteData();
wait_us(100);
#ifndef MD_BOOTLOADER
usb_extra_manual = 0;
usb_gcr_auto = 1;
#endif //MD_BOOTLOADER
@@ -147,22 +139,22 @@ void USB2422_init(void)
DBGC(DC_USB2422_INIT_COMPLETE);
}
void USB_reset(void)
{
void USB_reset(void) {
DBGC(DC_USB_RESET_BEGIN);
//pulse reset for at least 1 usec
sr_exp_data.bit.HUB_RESET_N = 0; //reset low
sr_exp_data.bit.HUB_RESET_N = 0; //reset low to reset
SR_EXP_WriteData();
wait_us(2);
sr_exp_data.bit.HUB_RESET_N = 1; //reset high to run
SR_EXP_WriteData();
wait_ms(10);
DBGC(DC_USB_RESET_COMPLETE);
}
void USB_configure(void)
{
void USB_configure(void) {
Usb2422 *pusb2422 = &USB2422_shadow;
memset(pusb2422, 0, sizeof(Usb2422));
@@ -177,15 +169,12 @@ void USB_configure(void)
DBGC(DC_USB_CONFIGURE_BEGIN);
if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) //Check for factory programmed serial address
{
if ((serial_address & 0xFF) % 4 == 0) //Check alignment
{
if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) { //Check for factory programmed serial address
if ((serial_address & 0xFF) % 4 == 0) { //Check alignment
serial_use = (uint16_t *)(serial_address);
serial_length = 0;
while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) &&
serial_length < BOOTLOADER_SERIAL_MAX_SIZE)
{
serial_length < BOOTLOADER_SERIAL_MAX_SIZE) {
serial_length++;
DBGC(DC_USB_CONFIGURE_GET_SERIAL);
}
@@ -215,126 +204,184 @@ void USB_configure(void)
pusb2422->STCD.bit.USB_ATTACH = 1;
USB_write2422_block();
adc_extra = 0;
DBGC(DC_USB_CONFIGURE_COMPLETE);
}
uint16_t USB_active(void)
{
uint16_t USB_active(void) {
return (PORT->Group[USB2422_HUB_ACTIVE_GROUP].IN.reg & (1 << USB2422_HUB_ACTIVE_PIN)) != 0;
}
void USB_set_host_by_voltage(void)
{
//UP is upstream device (HOST)
//DN1 is downstream device (EXTRA)
//DN2 is keyboard (KEYB)
#define USB_DETECT_INIT_VAL 100 //Default value for rp/cc detection to test against after routines
#define USB_DETECT_METHOD_NONE 0
#define USB_DETECT_METHOD_RP 1
#define USB_DETECT_METHOD_V 2
DBGC(DC_USB_SET_HOST_BY_VOLTAGE_BEGIN);
//Return best Rp value match
uint8_t USB_detect_host(void) {
static uint8_t usb_detect_onb_ext = 0;
uint8_t rp_best_index = 0;
usb_host_port = USB_HOST_PORT_UNKNOWN;
#ifndef MD_BOOTLOADER
usb_extra_state = USB_EXTRA_STATE_UNKNOWN;
#endif //MD_BOOTLOADER
sr_exp_data.bit.SRC_1 = 1; //USBC-1 available for test
sr_exp_data.bit.SRC_2 = 1; //USBC-2 available for test
sr_exp_data.bit.E_UP_N = 1; //HOST disable
sr_exp_data.bit.E_DN1_N = 1; //EXTRA disable
sr_exp_data.bit.E_VBUS_1 = 0; //USBC-1 disable full power I/O
sr_exp_data.bit.E_VBUS_2 = 0; //USBC-2 disable full power I/O
DBGC(DC_USB_DETECT_HOST_BEGIN);
SR_EXP_WriteData();
g_usb_host_port = USB_HOST_PORT_UNKNOWN; //Initialize host port as unknown
wait_ms(250);
usb_init_host_detection_kb(); //Run keyboard specific initialization
while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB_SET_HOST_5V_LOW_WAITING); }
wait_ms(100); //Allow power dissapation time on CC lines
v_con_1 = adc_get(ADC_CON1);
v_con_2 = adc_get(ADC_CON2);
while (adc_get(ADC_5V) < ADC_5V_V2C(ADC_5V_START_LEVEL)) { DBGC(DC_USB_DETECT_HOST_5V_LOW_WAITING); } //Assert 5V bus adequate
v_con_1_boot = v_con_1;
v_con_2_boot = v_con_2;
uint8_t detect_method = USB_DETECT_METHOD_NONE; //Initial detection method
uint8_t adc_cc_index[] = { ADC_C1A5, ADC_C1B5, ADC_C2A5, ADC_C2B5 }; //Initialize CC lines array
uint16_t cc_readings[] = { 0, 0, 0, 0 }; //Initialize CC readings array
uint8_t cc_index;
uint8_t cc_index_max = sizeof(adc_cc_index) / sizeof(*adc_cc_index);
if (v_con_1 > v_con_2)
{
sr_exp_data.bit.S_UP = 0; //HOST to USBC-1
sr_exp_data.bit.S_DN1 = 1; //EXTRA to USBC-2
sr_exp_data.bit.SRC_1 = 1; //HOST on USBC-1
sr_exp_data.bit.SRC_2 = 0; //EXTRA available on USBC-2
//Collect CC readings for decision making processes
for (cc_index = 0; cc_index < cc_index_max; cc_index++) { //For each CC line
cc_readings[cc_index] = adc_get(adc_cc_index[cc_index]); //Perform ADC reading
if (cc_readings[cc_index] == (uint16_t)ADC_NA) { //If the ADC was not available for reading
cc_readings[cc_index] = 0; //Set value low to not be used
continue; //ADC not available so skip
}
sr_exp_data.bit.E_VBUS_1 = 1; //USBC-1 enable full power I/O
sr_exp_data.bit.E_VBUS_2 = 0; //USBC-2 disable full power I/O
SR_EXP_WriteData();
sr_exp_data.bit.E_UP_N = 0; //HOST enable
SR_EXP_WriteData();
usb_host_port = USB_HOST_PORT_1;
}
else
{
sr_exp_data.bit.S_UP = 1; //EXTRA to USBC-1
sr_exp_data.bit.S_DN1 = 0; //HOST to USBC-2
sr_exp_data.bit.SRC_1 = 0; //EXTRA available on USBC-1
sr_exp_data.bit.SRC_2 = 1; //HOST on USBC-2
sr_exp_data.bit.E_VBUS_1 = 0; //USBC-1 disable full power I/O
sr_exp_data.bit.E_VBUS_2 = 1; //USBC-2 enable full power I/O
SR_EXP_WriteData();
sr_exp_data.bit.E_UP_N = 0; //HOST enable
SR_EXP_WriteData();
usb_host_port = USB_HOST_PORT_2;
cc_readings[cc_index] = ADC_CC_5VCOR(adc_get(ADC_5V), cc_readings[cc_index]); //Correct the ADC reading according to 5V bus
}
#ifndef MD_BOOTLOADER
usb_extra_state = USB_EXTRA_STATE_DISABLED;
#endif //MD_BOOTLOADER
#ifdef ADC_USBC_RP_DELTA_MAX
if (detect_method == USB_DETECT_METHOD_NONE) { //If a detection method has not succeeded yet
//Using CC readings, test them for onb or ext
uint16_t rp_delta_least = 5000; //Initialize to a high number out of ADC range
uint16_t rp_delta; //Distance of reading to a test value
uint8_t rp_index; //Index of Rp value being tested
uint8_t cc_best_index = USB_DETECT_INIT_VAL; //Initialize to a high number out of index
USB_reset();
USB_configure();
rp_best_index = USB_DETECT_INIT_VAL; //Initialize to a high number out of index
for (cc_index = 0; cc_index < cc_index_max; cc_index++) { //For each CC line
for (rp_index = 0; rp_index < ADC_USBC_TYPES; rp_index++) { //For each Rp
rp_delta = abs(cc_readings[cc_index] - adc_usbc_rp_nominal[rp_index]); //Calculate the distance between reading and Rp
if (rp_delta < rp_delta_least && rp_delta < ADC_USBC_RP_DELTA_MAX) { //If the distance is less than the least and within distance cap
rp_delta_least = rp_delta; //Save the least rp distance
rp_best_index = rp_index; //Save the closest Rp value index
cc_best_index = adc_cc_index[cc_index]; //Save the closest CC line index
}
}
}
DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE);
//Set up host port and extra port according to detection
if (rp_best_index != USB_DETECT_INIT_VAL) { //If a decision was made
if (cc_best_index == ADC_C1A5 || cc_best_index == ADC_C1B5) { //If on CON1
usb_set_host_kb(1, rp_best_index); //Set up host port on CON1 (rp used to set onb/ext)
usb_set_extra_kb(2); //Set up extra port on CON2
detect_method = USB_DETECT_METHOD_RP; //Set detection method used
} else if (cc_best_index == ADC_C2A5 || cc_best_index == ADC_C2B5) { //Else if on CON2
usb_set_host_kb(2, rp_best_index); //Set up host port on CON2 (rp used to set onb/ext)
usb_set_extra_kb(1); //Set up extra port on CON1
detect_method = USB_DETECT_METHOD_RP; //Set detection method used
}
}
}
#endif
//Detect highest voltage port and test onboard or external
if (detect_method == USB_DETECT_METHOD_NONE) { //If a detection method has not succeeded yet
uint16_t rp_highest_v = 0; //Initialize to the lowest number possible
uint8_t v_best_index = USB_DETECT_INIT_VAL; //Initialize to the lowest number possible
for (cc_index = 0; cc_index < cc_index_max; cc_index++) { //For each CC line
if (cc_readings[cc_index] > rp_highest_v) { //Keep track of the highest voltage level as a secondary host detection method
rp_highest_v = cc_readings[cc_index]; //Save the highest voltage
v_best_index = adc_cc_index[cc_index]; //Save the highest voltage index
}
}
//Set up host port and extra port according to detection
usb_detect_onb_ext = !usb_detect_onb_ext; //Swap onb/ext detect for this run
rp_best_index = usb_detect_onb_ext; //Force onb/ext setting
if (v_best_index == ADC_C1A5 || v_best_index == ADC_C1B5) { //If on CON1
usb_set_host_kb(1, rp_best_index); //Set up host port on CON1
usb_set_extra_kb(2); //Set up extra port on CON2
detect_method = USB_DETECT_METHOD_V; //Set detection method used
} else if (v_best_index == ADC_C2A5 || v_best_index == ADC_C2B5) { //Else if on CON2
usb_set_host_kb(2, rp_best_index); //Set up host port on CON2
usb_set_extra_kb(1); //Set up extra port on CON1
detect_method = USB_DETECT_METHOD_V; //Set detection method used
}
}
if (detect_method != USB_DETECT_METHOD_NONE) { //If a detection method succeeded
wait_ms(20); //Allow settling time for switching
USB_reset(); //Reset and enable the USB Hub
USB_configure(); //Configure the USB Hub and send attach
}
DBGC(DC_USB_DETECT_HOST_COMPLETE);
return rp_best_index;
}
uint8_t USB2422_Port_Detect_Init(void)
{
uint32_t port_detect_retry_ms;
uint8_t USB2422_Port_Detect_Init(void) {
uint32_t tmod;
uint8_t led_state = 0;
uint64_t port_detect_fail_ms;
static uint8_t port_detect_retry_counter = 0;
static uint16_t port_detect_retry_ms = 0;
DBGC(DC_PORT_DETECT_INIT_BEGIN);
USB_set_host_by_voltage();
#ifdef ADC_USBC_IS_EXT
//If the keyboard supports offboard USB extenders, rp_best_index is used to determine onboard/offboard usage
uint8_t rp_best_index = USB_detect_host();
#else
USB_detect_host();
#endif
port_detect_retry_ms = timer_read64() + PORT_DETECT_RETRY_INTERVAL;
port_detect_fail_ms = timer_read64() + PORT_DETECT_RETRY_START + port_detect_retry_ms;
uint32_t port_flash_counter = timer_read();
while (!USB_active())
{
tmod = timer_read64() % PORT_DETECT_RETRY_INTERVAL;
if (v_con_1 > v_con_2) //Values updated from USB_set_host_by_voltage();
{
//1 flash for port 1 detected
if (tmod > 500 && tmod < 600) { DBG_LED_ON; }
else { DBG_LED_OFF; }
}
else if (v_con_2 > v_con_1) //Values updated from USB_set_host_by_voltage();
{
//2 flash for port 2 detected
if (tmod > 500 && tmod < 600) { DBG_LED_ON; }
else if (tmod > 700 && tmod < 800) { DBG_LED_ON; }
else { DBG_LED_OFF; }
while (!USB_active()) {
tmod = (timer_read() - port_flash_counter);
if (USB_HOST_IS_1(g_usb_host_port)) {
//1 flash for port 1 detected (dit), additional long flash if external port (dit-dah)
if (tmod > 500 && tmod < 600) {
if (!led_state) { DBG_LED_ON; led_state = 1; }
}
#ifdef ADC_USBC_IS_EXT
else if (ADC_USBC_IS_EXT(rp_best_index) && tmod > 1000 && tmod < 1500) {
if (!led_state) { DBG_LED_ON; led_state = 1; }
}
#endif
else if (led_state) { DBG_LED_OFF; led_state = 0; }
} else if (USB_HOST_IS_2(g_usb_host_port)) {
//2 flash for port 2 detected (dit-dit), additional long flash if external port (dit-dit-dah)
if (tmod > 500 && tmod < 600) {
if (!led_state) { DBG_LED_ON; led_state = 1; }
} else if (tmod > 700 && tmod < 800) {
if (!led_state) { DBG_LED_ON; led_state = 1; }
}
#ifdef ADC_USBC_IS_EXT
else if (ADC_USBC_IS_EXT(rp_best_index) && tmod > 1000 && tmod < 1500) {
if (!led_state) { DBG_LED_ON; led_state = 1; }
}
#endif
else if (led_state) { DBG_LED_OFF; led_state = 0; }
} else {
//Flash every 250ms if port unknown (should not get here)
if (tmod % 500 < 250) {
if (!led_state) { DBG_LED_ON; led_state = 1; }
} else if (led_state) { DBG_LED_OFF; led_state = 0; }
}
if (timer_read64() > port_detect_retry_ms)
{
if (timer_read64() > port_detect_fail_ms) { //If timeout reached
DBGC(DC_PORT_DETECT_INIT_FAILED);
port_detect_retry_counter++; //Increment retry counter
if (port_detect_retry_counter % 2 == 0) { //Increment timeout every 2 attempts
port_detect_retry_ms += PORT_DETECT_RETRY_INCREMENT; //Increment timeout
}
if (port_detect_retry_ms > PORT_DETECT_RETRY_MAX) { //If the new timeout is greater than the max timeout setting
port_detect_retry_ms = PORT_DETECT_RETRY_MAX; //Set timeout to max
}
return 0;
}
}
@@ -346,64 +393,207 @@ uint8_t USB2422_Port_Detect_Init(void)
#ifndef MD_BOOTLOADER
void USB_ExtraSetState(uint8_t state)
{
uint8_t state_save = state;
usbc_t usbc;
if (state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG)
state = USB_EXTRA_STATE_DISABLED;
uint16_t usbc_cc_a5_v;
uint16_t usbc_cc_b5_v;
float usbc_cc_a5_v_avg;
float usbc_cc_b5_v_avg;
if (usb_host_port == USB_HOST_PORT_1) sr_exp_data.bit.E_VBUS_2 = state;
else if (usb_host_port == USB_HOST_PORT_2) sr_exp_data.bit.E_VBUS_1 = state;
else return;
sr_exp_data.bit.E_DN1_N = !state;
SR_EXP_WriteData();
usb_extra_state = state_save;
if (usb_extra_state == USB_EXTRA_STATE_ENABLED) CDC_print("USB: Extra enabled\r\n");
else if (usb_extra_state == USB_EXTRA_STATE_DISABLED)
{
CDC_print("USB: Extra disabled\r\n");
#ifdef USE_MASSDROP_CONFIGURATOR
if (led_animation_breathing) gcr_breathe = gcr_desired;
#endif
}
else if (usb_extra_state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) CDC_print("USB: Extra disabled until replug\r\n");
else CDC_print("USB: Extra state unknown\r\n");
void usbc_cc_clear(void) {
usbc_cc_a5_v = 0;
usbc_cc_b5_v = 0;
usbc_cc_a5_v_avg = 0.0f;
usbc_cc_b5_v_avg = 0.0f;
}
void USB_HandleExtraDevice(void)
{
uint16_t adcval;
if (usb_host_port == USB_HOST_PORT_1) adcval = adc_get(ADC_CON2);
else if (usb_host_port == USB_HOST_PORT_2) adcval = adc_get(ADC_CON1);
else return;
adc_extra = adc_extra * 0.9 + adcval * 0.1;
//Check for a forced disable state (such as overload prevention)
if (usb_extra_state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG)
{
//Detect unplug and reset state to disabled
if (adc_extra > USB_EXTRA_ADC_THRESHOLD) usb_extra_state = USB_EXTRA_STATE_DISABLED;
return; //Return even if unplug detected
//Only poll CC lines for port assigned as EXTRA
uint8_t usbc_cc_update(void) {
if (USB_HOST_IS_1(g_usb_host_port)) {
usbc_cc_a5_v = adc_get(ADC_C2A5);
usbc_cc_b5_v = adc_get(ADC_C2B5);
} else if (USB_HOST_IS_2(g_usb_host_port)) {
usbc_cc_a5_v = adc_get(ADC_C1A5);
usbc_cc_b5_v = adc_get(ADC_C1B5);
} else {
return 0;
}
if (usb_extra_manual)
{
if (usb_extra_state == USB_EXTRA_STATE_DISABLED)
USB_ExtraSetState(USB_EXTRA_STATE_ENABLED);
usbc_cc_a5_v_avg = 0.9 * usbc_cc_a5_v_avg + 0.1 * (float)usbc_cc_a5_v;
usbc_cc_b5_v_avg = 0.9 * usbc_cc_b5_v_avg + 0.1 * (float)usbc_cc_b5_v;
return;
return 1;
}
//Disable 5V bus on extra USB port
//If force_update != 0, force update to run
//If force_update == 0, only update if value is changed
uint8_t usbc_5v_disable(uint8_t force_update) {
if (USB_HOST_IS_1(g_usb_host_port)) {
if (force_update || (USBC_CFG_5V2_VAR != USBC_CFG_5V2_DIS)) {
USBC_CFG_5V2_VAR = USBC_CFG_5V2_DIS;
USBC_CFG_5V2_UPDATE;
}
return 1;
} else if (USB_HOST_IS_2(g_usb_host_port)) {
if (force_update || (USBC_CFG_5V1_VAR != USBC_CFG_5V1_DIS)) {
USBC_CFG_5V1_VAR = USBC_CFG_5V1_DIS;
USBC_CFG_5V1_UPDATE;
}
return 1;
}
//dpf("a %i %i\r\n",adcval, adc_extra);
if (usb_extra_state == USB_EXTRA_STATE_DISABLED && adc_extra < USB_EXTRA_ADC_THRESHOLD) USB_ExtraSetState(USB_EXTRA_STATE_ENABLED);
else if (usb_extra_state == USB_EXTRA_STATE_ENABLED && adc_extra > USB_EXTRA_ADC_THRESHOLD) USB_ExtraSetState(USB_EXTRA_STATE_DISABLED);
return 0;
}
//Enable 5V bus on extra USB port
//If force_update != 0, force update to run
//If force_update == 0, only update if value is changed
uint8_t usbc_5v_enable(uint8_t force_update) {
if (USB_HOST_IS_1(g_usb_host_port)) {
if (force_update || (USBC_CFG_5V2_VAR != USBC_CFG_5V2_ENA)) {
USBC_CFG_5V2_VAR = USBC_CFG_5V2_ENA;
USBC_CFG_5V2_UPDATE;
}
return 1;
} else if (USB_HOST_IS_2(g_usb_host_port)) {
if (force_update || (USBC_CFG_5V1_VAR != USBC_CFG_5V1_ENA)) {
USBC_CFG_5V1_VAR = USBC_CFG_5V1_ENA;
USBC_CFG_5V1_UPDATE;
}
return 1;
}
return 0;
}
uint8_t usbc_5v_is_enabled(void) {
if (USB_HOST_IS_1(g_usb_host_port)) {
if (USBC_CFG_5V2_VAR == USBC_CFG_5V2_ENA) {
return 1;
} else {
return 0;
}
} else if (USB_HOST_IS_2(g_usb_host_port)) {
if (USBC_CFG_5V1_VAR == USBC_CFG_5V1_ENA) {
return 1;
} else {
return 0;
}
}
return 0; //Not sure technically due to unknown host port
}
void usbc_enable(void) {
usbc_5v_disable(1); //Disable 5V bus
usbc.state = USB_STATE_UNATTACHED_WAIT_SRC; //Set starting state to discharge wait
usbc.timer = USBC_CFG_TVCONNDISCHARGE; //Set timer for 5V bus discharge
usbc_cc_clear(); //Clear CC readings
}
void usbc_disable(void) {
usbc_5v_disable(1); //Disable 5V bus
usbc.state = USB_STATE_DISABLED_WAIT; //Set disabled waiting state
usbc.timer = USBC_CFG_TVCONNDISCHARGE; //Set timer for 5V bus discharge
usbc_cc_clear(); //Clear CC readings
}
//This macro updates the timer and returns true if timer is complete
#define USBC_TIMER_DONE (0 == (usbc.timer = (usbc.timer > USBC_CFG_PERIOD ? usbc.timer - USBC_CFG_PERIOD : 0)))
void usbc_task(void) {
if (usbc.state == USB_STATE_UNATTACHED_SRC) {
//Connection detected -> USB_STATE_ATTACH_WAIT_SRC
usbc.timer = 0; //Note: Changes to this state do not require clearing timer at change
if (usbc_cc_update()) { //Must have valid readings to continue
if (USBC_IS_SINK((uint16_t)usbc_cc_a5_v_avg, (uint16_t)usbc_cc_b5_v_avg)) { //If Sink detected
usbc.state = USB_STATE_ATTACH_WAIT_SRC; //Set next state
usbc.timer = USBC_CFG_TCCDEBOUNCE; //Set timer
} else {
return; //Nothing more to be done
}
}
}
if (usbc.state == USB_STATE_ATTACH_WAIT_SRC) {
//Connection removed -> USB_STATE_UNATTACHED_SRC
//Other detection types unsupported -> USB_STATE_UNATTACHED_SRC
if (!usbc_cc_update()) { //Must have valid readings to continue
usbc.state = USB_STATE_UNATTACHED_SRC; //Invalid reading, detach
return; //Nothing more to be done
} else { //Valid CC readings to work with
if (!USBC_IS_SINK((uint16_t)usbc_cc_a5_v_avg, (uint16_t)usbc_cc_b5_v_avg)) { //If not a sink type
usbc.state = USB_STATE_UNATTACHED_SRC; //Detach
return; //Nothing more to be done
} else {
//Detected Sink for tCCDebounce -> USB_STATE_ATTACHED_SRC
if (USBC_TIMER_DONE) { //Update timer and if timer complete
if (usb_attach_port_configure_kb(g_usb_host_port, (uint16_t)usbc_cc_a5_v_avg, (uint16_t)usbc_cc_b5_v_avg)) { //If configuration was successful
usbc_5v_enable(1); //Enable 5V bus
usbc.state = USB_STATE_ATTACHED_SRC; //Set next state
dprintf("USB Extra: Port enabled\n");
} else { //port was not configured
usbc.state = USB_STATE_UNATTACHED_SRC; //Set next state
}
}
}
}
}
if (usbc.state == USB_STATE_ATTACHED_SRC) {
//Sink Removed and VCONN was On -> USB_STATE_UNATTACHED_WAIT_SRC
//Sink removed and VCONN was Off -> USB_STATE_UNATTACHED_SRC (Will always assume VCONN was On so ignoring this)
if (!usbc_cc_update()) { //Must have valid readings to continue
usbc_5v_disable(1); //Disable 5V bus
usbc.state = USB_STATE_UNATTACHED_WAIT_SRC; //Enter wait state for 5V bus discharge
usbc.timer = USBC_CFG_TVCONNDISCHARGE; //Set timer for 5V bus discharge
dprintf("USB Extra: Port disabled\n");
} else {
if (!USBC_IS_SINK((uint16_t)usbc_cc_a5_v_avg, (uint16_t)usbc_cc_b5_v_avg)) { //Sink lost
usbc_5v_disable(1); //Disable 5V bus
usbc.state = USB_STATE_UNATTACHED_WAIT_SRC; //Enter wait state for 5V bus discharge
usbc.timer = USBC_CFG_TVCONNDISCHARGE; //Set timer for 5V bus discharge
dprintf("USB Extra: Port disabled\n");
}
}
}
if (usbc.state == USB_STATE_UNATTACHED_WAIT_SRC) {
//Discharge Complete and VCONN Off -> USB_STATE_UNATTACHED_SRC
if (USBC_TIMER_DONE) { //Update timer and if timer complete
usbc.state = USB_STATE_UNATTACHED_SRC; //Set next state
}
}
if (usbc.state == USB_STATE_DISABLED_WAIT) {
//Wait complete -> USB_STATE_DISABLED
if (USBC_TIMER_DONE) { //Update timer and if timer complete
usbc.state = USB_STATE_DISABLED; //Set next state
}
}
if (usbc.state == USB_STATE_DISABLED_UNTIL_DETACH) {
if (usbc_5v_is_enabled()) {
usbc_5v_disable(1); //Disable 5V bus
}
if (!usbc_cc_update()) { //Must have valid readings to continue
usbc.state = USB_STATE_UNATTACHED_WAIT_SRC; //Enter wait state for 5V bus discharge
usbc.timer = USBC_CFG_TVCONNDISCHARGE; //Set timer for 5V bus discharge
} else {
if (!USBC_IS_SINK((uint16_t)usbc_cc_a5_v_avg, (uint16_t)usbc_cc_b5_v_avg)) { //Sink lost
usbc.state = USB_STATE_UNATTACHED_WAIT_SRC; //Enter wait state for 5V bus discharge
usbc.timer = USBC_CFG_TVCONNDISCHARGE; //Set timer for 5V bus discharge
}
}
}
}
void USB_HandleExtraDevice(void) {
usbc_task();
}
#endif //MD_BOOTLOADER

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Massdrop Inc.
Copyright 2019 Massdrop Inc.
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
@@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef _USB2422_H_
#define _USB2422_H_
#include "config_usb.h" //From keyboard's directory
#define REV_USB2422 0x100
#define USB2422_ADDR 0x58 //I2C device address, one instance
@@ -372,33 +374,81 @@ typedef struct {
} Usb2422;
#endif
#define PORT_DETECT_RETRY_INTERVAL 2000
//When testing for USB enumeration, retry after this many ms
#define PORT_DETECT_RETRY_START 2000
#define PORT_DETECT_RETRY_INCREMENT 2000
#define PORT_DETECT_RETRY_MAX 10000
#define USB_EXTRA_ADC_THRESHOLD 900
//Onboard ports must have an even number
//External ports must have an odd number
//The only exception is the unknown state
#define USB_HOST_PORT_1 0
#define USB_HOST_PORT_1_EXT 1
#define USB_HOST_PORT_2 2
#define USB_HOST_PORT_2_EXT 3
#define USB_HOST_PORT_UNKNOWN 4
#define USB_EXTRA_STATE_DISABLED 0
#define USB_EXTRA_STATE_ENABLED 1
#define USB_EXTRA_STATE_UNKNOWN 2
#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3
//Macros to check host port assignment
#define USB_HOST_IS_1(host) (host == USB_HOST_PORT_1 || host == USB_HOST_PORT_1_EXT)
#define USB_HOST_IS_2(host) (host == USB_HOST_PORT_2 || host == USB_HOST_PORT_2_EXT)
#define USB_HOST_PORT_1 0
#define USB_HOST_PORT_2 1
#define USB_HOST_PORT_UNKNOWN 2
//Macros to test if the sink device is connected to the onboard or external port
//Note: USBC_IS_SINK defined in the keyboard's config_adc.h
#define USBC_IS_SINK_ONB(a5, b5) (ADC_USBC_IS_ONB(g_usb_host_port) && USBC_IS_SINK(a5, b5))
#define USBC_IS_SINK_EXT(a5, b5) (ADC_USBC_IS_EXT(g_usb_host_port) && USBC_IS_SINK(a5, b5))
extern uint8_t usb_host_port;
//Note: Due to the way timers are implemented, waits will always be slightly longer than defined
#define USBC_TIMER_ATTACH_WAIT 0
#define USBC_TIMER_DETACH 1 //tCCDebounce
#define USBC_CFG_PERIOD 5 //How often the extra USB port is checked (ms)(This multiple affects the accuracy of USB timers)
#define USBC_CFG_TCCDEBOUNCE 150 //tCCDebounce - Time a port shall wait before it can determine it is attached (ms)
#define USBC_CFG_TSRCDISCONNECT 0 //tSRCDisconnect - Time a Source shall detect the SRC.Open state (As fast as possible)(ms)
#define USBC_CFG_TVCONNDISCHARGE 100 //UnattachedWait time for VCONN discharge
#define USBC_CFG_TDISABLED 100 //Minimum time to wait after state machine disabled
#define USB_STATE_UNKNOWN 0 //Custom state for init
#define USB_STATE_UNATTACHED_SRC 1 //Directed from any state
//From USB_STATE_UNATTACHED_WAIT_SRC after Discharge Complete and Vconn Off
//From USB_STATE_ATTACHED_SRC if Sink Removed and Vconn was Off
//From USB_STATE_ATTACH_WAIT_SRC if Connection Removed
#define USB_STATE_ATTACH_WAIT_SRC 2 //From USB_STATE_UNATTACHED_SRC when Connection detected
#define USB_STATE_ATTACHED_SRC 3 //From USB_STATE_ATTACHWAIT_SRC when Vbus at vSafe0V and Sink Detected for tCCDebounce
#define USB_STATE_UNATTACHED_WAIT_SRC 4 //From USB_STATE_ATTACHED_SRC when Sink Removed and Vconn was On
#define USB_STATE_DISABLED_WAIT 100 //Custom state for USB 5V Bus discharge then to USB_STATE_DISABLED_WAIT
#define USB_STATE_DISABLED 101 //Directed from any state
#define USB_STATE_DISABLED_UNTIL_DETACH 102 //Custom state for when USB 5V Bus overloads and device must be detached before use
//USB Type-C State machine for a SOURCE
typedef struct usbc_s {
uint8_t state;
uint16_t timer;
} usbc_t;
extern uint8_t g_usb_host_port;
extern uint8_t usb_extra_state;
extern uint8_t usb_extra_manual;
extern uint8_t usb_gcr_auto;
extern usbc_t usbc;
extern uint16_t usbc_cc_a5_v;
extern uint16_t usbc_cc_b5_v;
extern float usbc_cc_a5_v_avg;
extern float usbc_cc_b5_v_avg;
void USB2422_init(void);
void USB_reset(void);
void USB_configure(void);
uint16_t USB_active(void);
void USB_set_host_by_voltage(void);
uint16_t adc_get(uint8_t muxpos);
uint8_t USB_detect_host(void);
uint8_t USB2422_Port_Detect_Init(void);
void USB_HandleExtraDevice(void);
void USB_ExtraSetState(uint8_t state);
void usbc_enable(void);
void usbc_disable(void);
void usbc_task(void);
//Keyboard defined functions
void usb_set_host_kb(uint8_t con, uint8_t rp_best_index);
void usb_set_extra_kb(uint8_t con);
void usb_init_host_detection_kb(void);
uint8_t usb_attach_port_configure_kb(uint8_t g_usb_host_port, uint16_t usbc_cc_a5_v, uint16_t usbc_cc_b5_v);
#endif //_USB2422_H_