Merge remote-tracking branch 'origin/md_1800_qmk'

This commit is contained in:
jonathan.liu
2019-07-12 00:49:08 -07:00
80 changed files with 5799 additions and 814 deletions

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

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");

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");

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,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");

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++)
{
@@ -85,7 +88,7 @@ uint8_t matrix_scan(void)
uint8_t mchanged;
uint8_t row;
uint8_t col;
uint32_t scans[2]; //PA PB
uint32_t scans[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
if (timer_read64() < mdebouncing) return 1; //mdebouncing == 0 when no debouncing active
@@ -93,14 +96,16 @@ uint8_t matrix_scan(void)
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++)
{

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

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");

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");

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");

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");

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++)
{
@@ -85,7 +88,7 @@ uint8_t matrix_scan(void)
uint8_t mchanged;
uint8_t row;
uint8_t col;
uint32_t scans[2]; //PA PB
uint32_t scans[MCU_PORTS_USED]; //Array size must match number of unique MCU ports used for reads (PA, PB, PC, etc)
if (timer_read64() < mdebouncing) return 1; //mdebouncing == 0 when no debouncing active
@@ -93,14 +96,16 @@ uint8_t matrix_scan(void)
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++)
{

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,129 @@
/*
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 DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
//#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
//#define LOCKING_RESYNC_ENABLE
/* 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,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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .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 = 255 }, \
{ .id = 85, .x = 0.74, .y = 1.5, .adr = { .drv = 2, .cs = 12, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
{ .id = 86, .x = 10.48, .y = 2.25, .adr = { .drv = 1, .cs = 3, .swr = 8, .swg = 7, .swb = 9 }, .scan = 255 }, \
{ .id = 87, .x = 10.48, .y = 1.5, .adr = { .drv = 1, .cs = 3, .swr = 11, .swg = 10, .swb = 12 }, .scan = 255 }, \
};
#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, _______, _______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_UP, _______, _______, U_T_AGCR,\
L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, KC_INS, KC_HOME, KC_PGUP, KC_LEFT, KC_DOWN, KC_RGHT, _______, \
_______, L_T_MD, L_T_ONF, _______, _______, 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) >= 500) {
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,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, _______, _______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_UP, _______, _______, U_T_AGCR,\
L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, KC_INS, KC_HOME, KC_PGUP, KC_LEFT, KC_DOWN, KC_RGHT, _______, \
_______, L_T_MD, L_T_ONF, _______, _______, 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) >= 500) {
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,181 @@
/*
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;
uint8_t matrix_scan(void)
{
uint8_t mchanged;
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)
if (timer_read64() < mdebouncing) return 1; //mdebouncing == 0 when no debouncing active
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;
}
}
mchanged = 0; //Default to no matrix change since last
for (row = 0; row < MATRIX_ROWS; row++)
{
if (mlast[row] != mlatest[row])
mchanged = 1;
mlast[row] = mlatest[row];
}
if (!mchanged)
{
for (row = 0; row < MATRIX_ROWS; row++)
mdebounced[row] = mlatest[row];
mdebouncing = 0;
}
else
{
//Begin or extend debounce on change
mdebouncing = timer_read64() + DEBOUNCING_DELAY;
}
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,159 @@
/*
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 DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
//#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
//#define LOCKING_RESYNC_ENABLE
/* 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,178 @@
#ifdef RGB_MATRIX_ENABLE
#include "shift.h"
#include "led_matrix.h"
#include "rgb_matrix.h"
#include "config_led.h"
const rgb_led g_rgb_leds[DRIVER_LED_TOTAL] = {
{ { 0|(0<<4) }, { 6, 5 }, 0 },
{ { 0|(1<<4) }, { 29, 5 }, 0 },
{ { 0|(2<<4) }, { 41, 5 }, 0 },
{ { 2|(2<<4) }, { 52, 5 }, 0 },
{ { 0|(3<<4) }, { 63, 5 }, 0 },
{ { 0|(4<<4) }, { 81, 5 }, 0 },
{ { 0|(5<<4) }, { 92, 5 }, 0 },
{ { 0|(6<<4) }, { 103, 5 }, 0 },
{ { 2|(6<<4) }, { 115, 5 }, 0 },
{ { 0|(7<<4) }, { 132, 5 }, 0 },
{ { 2|(7<<4) }, { 143, 5 }, 0 },
{ { 1|(0<<4) }, { 155, 5 }, 0 },
{ { 3|(0<<4) }, { 166, 5 }, 0 },
{ { 1|(1<<4) }, { 183, 5 }, 0 },
{ { 1|(2<<4) }, { 195, 5 }, 0 },
{ { 1|(3<<4) }, { 206, 5 }, 0 },
{ { 1|(4<<4) }, { 218, 5 }, 0 },
{ { 3|(1<<4) }, { 183, 13 }, 0 },
{ { 3|(2<<4) }, { 195, 13 }, 0 },
{ { 3|(3<<4) }, { 206, 13 }, 0 },
{ { 3|(4<<4) }, { 218, 13 }, 1 },
{ { 2|(0<<4) }, { 6, 22 }, 0 },
{ { 2|(1<<4) }, { 18, 22 }, 0 },
{ { 4|(1<<4) }, { 29, 22 }, 0 },
{ { 4|(2<<4) }, { 41, 22 }, 0 },
{ { 6|(2<<4) }, { 52, 22 }, 0 },
{ { 2|(3<<4) }, { 63, 22 }, 0 },
{ { 4|(3<<4) }, { 75, 22 }, 0 },
{ { 2|(4<<4) }, { 86, 22 }, 0 },
{ { 2|(5<<4) }, { 98, 22 }, 0 },
{ { 4|(5<<4) }, { 109, 22 }, 0 },
{ { 4|(6<<4) }, { 121, 22 }, 0 },
{ { 6|(6<<4) }, { 132, 22 }, 0 },
{ { 4|(7<<4) }, { 143, 22 }, 0 },
{ { 5|(0<<4) }, { 161, 22 }, 0 },
{ { 5|(1<<4) }, { 183, 22 }, 1 },
{ { 5|(2<<4) }, { 195, 22 }, 0 },
{ { 5|(3<<4) }, { 206, 22 }, 0 },
{ { 5|(4<<4) }, { 218, 22 }, 0 },
{ { 4|(0<<4) }, { 9, 31 }, 0 },
{ { 6|(1<<4) }, { 23, 31 }, 0 },
{ { 8|(1<<4) }, { 35, 31 }, 0 },
{ { 8|(2<<4) }, { 46, 31 }, 0 },
{ { 6|(3<<4) }, { 58, 31 }, 0 },
{ { 8|(3<<4) }, { 69, 31 }, 0 },
{ { 4|(4<<4) }, { 81, 31 }, 0 },
{ { 6|(4<<4) }, { 92, 31 }, 0 },
{ { 6|(5<<4) }, { 103, 31 }, 0 },
{ { 8|(5<<4) }, { 115, 31 }, 0 },
{ { 8|(6<<4) }, { 126, 31 }, 0 },
{ { 6|(7<<4) }, { 138, 31 }, 0 },
{ { 7|(0<<4) }, { 149, 31 }, 0 },
{ { 9|(0<<4) }, { 163, 31 }, 0 },
{ { 7|(1<<4) }, { 183, 31 }, 0 },
{ { 7|(2<<4) }, { 195, 31 }, 0 },
{ { 7|(3<<4) }, { 206, 31 }, 0 },
{ { 7|(4<<4) }, { 218, 31 }, 0 },
{ { 6|(0<<4) }, { 11, 40 }, 1 },
{ { 10|(1<<4) }, { 26, 40 }, 0 },
{ { 12|(1<<4) }, { 38, 40 }, 0 },
{ { 10|(2<<4) }, { 49, 40 }, 0 },
{ { 10|(3<<4) }, { 61, 40 }, 0 },
{ { 12|(3<<4) }, { 72, 40 }, 0 },
{ { 8|(4<<4) }, { 83, 40 }, 0 },
{ { 10|(4<<4) }, { 95, 40 }, 0 },
{ { 10|(5<<4) }, { 106, 40 }, 0 },
{ { 10|(6<<4) }, { 118, 40 }, 0 },
{ { 8|(7<<4) }, { 129, 40 }, 0 },
{ { 11|(0<<4) }, { 141, 40 }, 0 },
{ { 13|(0<<4) }, { 159, 40 }, 0 },
{ { 9|(1<<4) }, { 183, 40 }, 0 },
{ { 9|(2<<4) }, { 195, 40 }, 0 },
{ { 9|(3<<4) }, { 206, 40 }, 0 },
{ { 9|(4<<4) }, { 218, 40 }, 0 },
{ { 8|(0<<4) }, { 13, 48 }, 0 },
{ { 14|(1<<4) }, { 32, 48 }, 0 },
{ { 12|(2<<4) }, { 43, 48 }, 0 },
{ { 14|(2<<4) }, { 55, 48 }, 0 },
{ { 14|(3<<4) }, { 66, 48 }, 0 },
{ { 12|(4<<4) }, { 78, 48 }, 0 },
{ { 14|(5<<4) }, { 89, 48 }, 0 },
{ { 12|(5<<4) }, { 101, 48 }, 0 },
{ { 12|(6<<4) }, { 112, 48 }, 0 },
{ { 10|(7<<4) }, { 123, 48 }, 0 },
{ { 12|(7<<4) }, { 135, 48 }, 0 },
{ { 15|(0<<4) }, { 151, 48 }, 0 },
{ { 11|(1<<4) }, { 183, 48 }, 0 },
{ { 11|(2<<4) }, { 195, 48 }, 0 },
{ { 11|(3<<4) }, { 206, 48 }, 0 },
{ { 13|(1<<4) }, { 169, 51 }, 0 },
{ { 11|(4<<4) }, { 218, 53 }, 0 },
{ { 10|(0<<4) }, { 8, 57 }, 0 },
{ { 12|(0<<4) }, { 22, 57 }, 0 },
{ { 14|(0<<4) }, { 36, 57 }, 0 },
{ { 14|(4<<4) }, { 79, 57 }, 0 },
{ { 14|(6<<4) }, { 123, 57 }, 0 },
{ { 14|(7<<4) }, { 141, 57 }, 0 },
{ { 13|(3<<4) }, { 195, 57 }, 0 },
{ { 13|(4<<4) }, { 206, 57 }, 0 },
{ { 15|(1<<4) }, { 158, 59 }, 0 },
{ { 15|(2<<4) }, { 169, 59 }, 0 },
{ { 13|(2<<4) }, { 181, 59 }, 0 },
{ { 0xFF }, { 2, 1 }, 0 },
{ { 0xFF }, { 12, 0 }, 0 },
{ { 0xFF }, { 32, 0 }, 0 },
{ { 0xFF }, { 42, 0 }, 0 },
{ { 0xFF }, { 52, 0 }, 0 },
{ { 0xFF }, { 62, 0 }, 0 },
{ { 0xFF }, { 72, 0 }, 0 },
{ { 0xFF }, { 82, 0 }, 0 },
{ { 0xFF }, { 92, 0 }, 0 },
{ { 0xFF }, { 102, 0 }, 0 },
{ { 0xFF }, { 112, 0 }, 0 },
{ { 0xFF }, { 122, 0 }, 0 },
{ { 0xFF }, { 132, 0 }, 0 },
{ { 0xFF }, { 142, 0 }, 0 },
{ { 0xFF }, { 152, 0 }, 0 },
{ { 0xFF }, { 162, 0 }, 0 },
{ { 0xFF }, { 172, 0 }, 0 },
{ { 0xFF }, { 182, 0 }, 0 },
{ { 0xFF }, { 192, 0 }, 0 },
{ { 0xFF }, { 212, 0 }, 0 },
{ { 0xFF }, { 222, 1 }, 0 },
{ { 0xFF }, { 224, 9 }, 0 },
{ { 0xFF }, { 224, 17 }, 0 },
{ { 0xFF }, { 224, 24 }, 0 },
{ { 0xFF }, { 224, 32 }, 0 },
{ { 0xFF }, { 224, 40 }, 0 },
{ { 0xFF }, { 224, 47 }, 0 },
{ { 0xFF }, { 224, 55 }, 0 },
{ { 0xFF }, { 222, 63 }, 0 },
{ { 0xFF }, { 212, 64 }, 0 },
{ { 0xFF }, { 202, 64 }, 0 },
{ { 0xFF }, { 192, 64 }, 0 },
{ { 0xFF }, { 182, 64 }, 0 },
{ { 0xFF }, { 172, 64 }, 0 },
{ { 0xFF }, { 162, 64 }, 0 },
{ { 0xFF }, { 152, 64 }, 0 },
{ { 0xFF }, { 142, 64 }, 0 },
{ { 0xFF }, { 132, 64 }, 0 },
{ { 0xFF }, { 122, 64 }, 0 },
{ { 0xFF }, { 112, 64 }, 0 },
{ { 0xFF }, { 102, 64 }, 0 },
{ { 0xFF }, { 92, 64 }, 0 },
{ { 0xFF }, { 82, 64 }, 0 },
{ { 0xFF }, { 72, 64 }, 0 },
{ { 0xFF }, { 62, 64 }, 0 },
{ { 0xFF }, { 52, 64 }, 0 },
{ { 0xFF }, { 42, 64 }, 0 },
{ { 0xFF }, { 32, 64 }, 0 },
{ { 0xFF }, { 22, 64 }, 0 },
{ { 0xFF }, { 12, 64 }, 0 },
{ { 0xFF }, { 2, 63 }, 0 },
{ { 0xFF }, { 0, 55 }, 0 },
{ { 0xFF }, { 0, 47 }, 0 },
{ { 0xFF }, { 0, 40 }, 0 },
{ { 0xFF }, { 0, 32 }, 0 },
{ { 0xFF }, { 0, 24 }, 0 },
{ { 0xFF }, { 0, 17 }, 0 },
{ { 0xFF }, { 0, 9 }, 0 },
};
#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) >= 500) {
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) >= 500) {
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,210 @@
/*
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;
uint8_t matrix_scan(void)
{
uint8_t mchanged;
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)
if (timer_read64() < mdebouncing) return 1; //mdebouncing == 0 when no debouncing active
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;
}
}
mchanged = 0; //Default to no matrix change since last
for (row = 0; row < MATRIX_ROWS; row++)
{
if (mlast[row] != mlatest[row])
mchanged = 1;
mlast[row] = mlatest[row];
}
if (!mchanged)
{
for (row = 0; row < MATRIX_ROWS; row++)
mdebounced[row] = mlatest[row];
mdebouncing = 0;
}
else
{
//Begin or extend debounce on change
mdebouncing = timer_read64() + DEBOUNCING_DELAY;
}
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

@@ -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,4 +1,4 @@
#include "d51_util.h"
#include "arm_atsam_protocol.h"
static volatile uint32_t w;

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"
@@ -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
@@ -64,120 +64,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
}
}
}
@@ -229,7 +232,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
}
}
@@ -249,7 +252,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);
@@ -257,16 +260,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;
@@ -274,47 +295,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)
@@ -342,9 +351,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;
}
}
}
@@ -372,15 +388,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
@@ -431,22 +463,56 @@ 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_rgb_leds[i].point.y / 64.f * 100
: (float)g_rgb_leds[i].point.x / 224.f * 100;
float po;
uint8_t highest_active_layer = biton32(layer_state);
if (led_lighting_mode == LED_MODE_KEYS_ONLY && g_rgb_leds[i].matrix_co.raw == 0xff) {
if (led_animation_circular) {
po = sqrtf((powf(fabsf((224 / 2) - (float)g_rgb_leds[i].point.x), 2) + powf(fabsf((64 / 2) - (float)g_rgb_leds[i].point.y), 2))) / RGB_MAX_DISTANCE * 100;
} else {
if (led_animation_orientation) {
po = (float)g_rgb_leds[i].point.y / 64.f * 100;
} else {
po = (float)g_rgb_leds[i].point.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 && g_rgb_leds[i].matrix_co.raw != 0xff) {
} else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && !LED_IS_EDGE(led_map[i].scan)) {
//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 {
@@ -482,6 +548,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;
@@ -494,9 +561,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;
@@ -14,12 +13,3 @@ extern uint32_t _eram;
#define MAGIC_ADDR (uint32_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_