forked from mirror/qmk_firmware
Upstream merge up to 02d44beb44
This commit is contained in:
@@ -4,7 +4,10 @@ SRC += $(ARM_ATSAM_DIR)/adc.c
|
||||
SRC += $(ARM_ATSAM_DIR)/clks.c
|
||||
SRC += $(ARM_ATSAM_DIR)/d51_util.c
|
||||
SRC += $(ARM_ATSAM_DIR)/i2c_master.c
|
||||
SRC += $(ARM_ATSAM_DIR)/led_matrix.c
|
||||
ifeq ($(RGB_MATRIX_ENABLE),custom)
|
||||
SRC += $(ARM_ATSAM_DIR)/led_matrix_programs.c
|
||||
SRC += $(ARM_ATSAM_DIR)/led_matrix.c
|
||||
endif
|
||||
SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c
|
||||
SRC += $(ARM_ATSAM_DIR)/spi.c
|
||||
SRC += $(ARM_ATSAM_DIR)/startup.c
|
||||
|
||||
@@ -74,9 +74,9 @@ void ADC0_init(void)
|
||||
while (ADC0->SYNCBUSY.bit.SAMPCTRL) { DBGC(DC_ADC0_SAMPCTRL_SYNCING_1); }
|
||||
|
||||
//Load factory calibration data
|
||||
ADC0->CALIB.bit.BIASCOMP = (ADC0_FUSES_BIASCOMP_ADDR >> ADC0_FUSES_BIASCOMP_Pos) & ADC0_FUSES_BIASCOMP_Msk;
|
||||
ADC0->CALIB.bit.BIASR2R = (ADC0_FUSES_BIASR2R_ADDR >> ADC0_FUSES_BIASR2R_Pos) & ADC0_FUSES_BIASR2R_Msk;
|
||||
ADC0->CALIB.bit.BIASREFBUF = (ADC0_FUSES_BIASREFBUF_ADDR >> ADC0_FUSES_BIASREFBUF_Pos) & ADC0_FUSES_BIASREFBUF_Msk;
|
||||
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;
|
||||
|
||||
@@ -21,8 +21,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "samd51j18a.h"
|
||||
#include "md_bootloader.h"
|
||||
|
||||
#include "timer.h"
|
||||
#include "d51_util.h"
|
||||
#include "clks.h"
|
||||
#include "wait.h"
|
||||
#include "adc.h"
|
||||
#include "i2c_master.h"
|
||||
#include "spi.h"
|
||||
@@ -32,7 +34,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
#include "main_arm_atsam.h"
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
#include "led_matrix.h"
|
||||
#include "rgb_matrix.h"
|
||||
#endif
|
||||
#include "issi3733_driver.h"
|
||||
#include "./usb/compiler.h"
|
||||
#include "./usb/udc.h"
|
||||
|
||||
@@ -21,8 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
volatile clk_t system_clks;
|
||||
volatile uint64_t ms_clk;
|
||||
|
||||
volatile uint8_t us_delay_done;
|
||||
uint32_t usec_delay_mult;
|
||||
#define USEC_DELAY_LOOP_CYCLES 3 //Sum of instruction cycles in us delay loop
|
||||
|
||||
const uint32_t sercom_apbbase[] = {(uint32_t)SERCOM0,(uint32_t)SERCOM1,(uint32_t)SERCOM2,(uint32_t)SERCOM3,(uint32_t)SERCOM4,(uint32_t)SERCOM5};
|
||||
const uint8_t sercom_pchan[] = {7, 8, 23, 24, 34, 35};
|
||||
@@ -73,6 +73,9 @@ void CLK_oscctrl_init(void)
|
||||
|
||||
system_clks.freq_gclk[0] = system_clks.freq_dpll[0];
|
||||
|
||||
usec_delay_mult = system_clks.freq_gclk[0] / (USEC_DELAY_LOOP_CYCLES * 1000000);
|
||||
if (usec_delay_mult < 1) usec_delay_mult = 1; //Never allow a multiplier of zero
|
||||
|
||||
DBGC(DC_CLK_OSC_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
@@ -158,23 +161,11 @@ void TC4_Handler()
|
||||
}
|
||||
}
|
||||
|
||||
void TC5_Handler()
|
||||
{
|
||||
if (TC5->COUNT16.INTFLAG.bit.MC0)
|
||||
{
|
||||
TC5->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0;
|
||||
us_delay_done = 1;
|
||||
TC5->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CLK_enable_timebase(void)
|
||||
{
|
||||
Gclk *pgclk = GCLK;
|
||||
Mclk *pmclk = MCLK;
|
||||
Tc *ptc4 = TC4;
|
||||
Tc *ptc5 = TC5;
|
||||
Tc *ptc0 = TC0;
|
||||
Evsys *pevsys = EVSYS;
|
||||
|
||||
@@ -189,11 +180,6 @@ uint32_t CLK_enable_timebase(void)
|
||||
pgclk->PCHCTRL[TC4_GCLK_ID].bit.GEN = GEN_TC45;
|
||||
pgclk->PCHCTRL[TC4_GCLK_ID].bit.CHEN = 1;
|
||||
|
||||
//unmask TC5 sourcegclk2 to TC5
|
||||
pmclk->APBCMASK.bit.TC5_ = 1;
|
||||
pgclk->PCHCTRL[TC5_GCLK_ID].bit.GEN = GEN_TC45;
|
||||
pgclk->PCHCTRL[TC5_GCLK_ID].bit.CHEN = 1;
|
||||
|
||||
//configure TC4
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN);
|
||||
ptc4->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
@@ -220,30 +206,6 @@ uint32_t CLK_enable_timebase(void)
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE);
|
||||
|
||||
//configure TC5
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_BEGIN);
|
||||
ptc5->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
while (ptc5->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_DISABLE); }
|
||||
ptc5->COUNT16.CTRLA.bit.SWRST = 1;
|
||||
while (ptc5->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_1); }
|
||||
while (ptc5->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_2); }
|
||||
|
||||
//CTRLA defaults
|
||||
//CTRLB as default, counting up
|
||||
ptc5->COUNT16.CTRLBCLR.reg = 5;
|
||||
while (ptc5->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_CLTRB); }
|
||||
//ptc5->COUNT16.DBGCTRL.bit.DBGRUN = 1;
|
||||
|
||||
//wave mode
|
||||
ptc5->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match
|
||||
//generate event for next stage
|
||||
ptc5->COUNT16.EVCTRL.bit.MCEO0 = 1;
|
||||
|
||||
NVIC_EnableIRQ(TC5_IRQn);
|
||||
ptc5->COUNT16.INTENSET.bit.MC0 = 1;
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_COMPLETE);
|
||||
|
||||
//unmask TC0,1, sourcegclk2 to TC0,1
|
||||
pmclk->APBAMASK.bit.TC0_ = 1;
|
||||
pgclk->PCHCTRL[TC0_GCLK_ID].bit.GEN = GEN_TC45;
|
||||
@@ -289,37 +251,27 @@ uint32_t CLK_enable_timebase(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t CLK_get_ms(void)
|
||||
void CLK_delay_us(uint32_t usec)
|
||||
{
|
||||
return ms_clk;
|
||||
}
|
||||
|
||||
void CLK_delay_us(uint16_t usec)
|
||||
{
|
||||
us_delay_done = 0;
|
||||
|
||||
if (TC5->COUNT16.CTRLA.bit.ENABLE)
|
||||
{
|
||||
TC5->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
|
||||
}
|
||||
|
||||
if (usec < 10) usec = 0;
|
||||
else usec -= 10;
|
||||
|
||||
TC5->COUNT16.CC[0].reg = usec;
|
||||
while (TC5->COUNT16.SYNCBUSY.bit.CC0) {}
|
||||
|
||||
TC5->COUNT16.CTRLA.bit.ENABLE = 1;
|
||||
while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
|
||||
|
||||
while (!us_delay_done) {}
|
||||
asm (
|
||||
"CBZ R0, return\n\t" //If usec == 0, branch to return label
|
||||
);
|
||||
asm (
|
||||
"MULS R0, %0\n\t" //Multiply R0(usec) by usec_delay_mult and store in R0
|
||||
".balign 16\n\t" //Ensure loop is aligned for fastest performance
|
||||
"loop: SUBS R0, #1\n\t" //Subtract 1 from R0 and update flags (1 cycle)
|
||||
"BNE loop\n\t" //Branch if non-zero to loop label (2 cycles) NOTE: USEC_DELAY_LOOP_CYCLES is the sum of loop cycles
|
||||
"return:\n\t" //Return label
|
||||
: //No output registers
|
||||
: "r" (usec_delay_mult) //For %0
|
||||
);
|
||||
//Note: BX LR generated
|
||||
}
|
||||
|
||||
void CLK_delay_ms(uint64_t msec)
|
||||
{
|
||||
msec += CLK_get_ms();
|
||||
while (msec > CLK_get_ms()) {}
|
||||
msec += timer_read64();
|
||||
while (msec > timer_read64()) {}
|
||||
}
|
||||
|
||||
void clk_enable_sercom_apbmask(int sercomn)
|
||||
|
||||
@@ -77,9 +77,8 @@ void CLK_oscctrl_init(void);
|
||||
void CLK_reset_time(void);
|
||||
uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq);
|
||||
uint32_t CLK_enable_timebase(void);
|
||||
uint32_t CLK_get_ms(void);
|
||||
uint64_t CLK_get_us(void);
|
||||
void CLK_delay_us(uint16_t usec);
|
||||
uint64_t timer_read64(void);
|
||||
void CLK_delay_us(uint32_t usec);
|
||||
void CLK_delay_ms(uint64_t msec);
|
||||
|
||||
uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq);
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "d51_util.h"
|
||||
|
||||
//Display unsigned 32-bit number through m15
|
||||
//Read as follows: 1230 = || ||| |||| | (note always ending toggle)
|
||||
void m15_print(uint32_t x)
|
||||
static volatile uint32_t w;
|
||||
|
||||
//Display unsigned 32-bit number by port toggling DBG_1 (to view on a scope)
|
||||
//Read as follows: 1230 = | | | | | | || (note zero is fast double toggle)
|
||||
#define DBG_PAUSE 5
|
||||
void dbg_print(uint32_t x)
|
||||
{
|
||||
int8_t t;
|
||||
uint32_t n;
|
||||
@@ -26,24 +29,34 @@ void m15_print(uint32_t x)
|
||||
while (p2--) p *= 10;
|
||||
n = x / p;
|
||||
x -= n * p;
|
||||
while (n > 0)
|
||||
if (!n)
|
||||
{
|
||||
m15_on;
|
||||
DBG_1_ON;
|
||||
DBG_1_OFF;
|
||||
DBG_1_ON;
|
||||
DBG_1_OFF;
|
||||
n--;
|
||||
m15_off;
|
||||
}
|
||||
//Will always end with an extra toggle
|
||||
m15_on;
|
||||
else
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
DBG_1_ON;
|
||||
DBG_1_OFF;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
t--;
|
||||
m15_off;
|
||||
}
|
||||
|
||||
for (w = DBG_PAUSE; w; w--); //Long pause after number is complete
|
||||
}
|
||||
|
||||
//Display unsigned 32-bit number through debug led
|
||||
//Read as follows: 1230 = [*] [* *] [* * *] [**] (note zero is fast double flash)
|
||||
#define DLED_ONTIME 1000000
|
||||
#define DLED_PAUSE 1500000
|
||||
volatile uint32_t w;
|
||||
void dled_print(uint32_t x, uint8_t long_pause)
|
||||
{
|
||||
int8_t t;
|
||||
@@ -70,13 +83,13 @@ void dled_print(uint32_t x, uint8_t long_pause)
|
||||
x -= n * p;
|
||||
if (!n)
|
||||
{
|
||||
led_on;
|
||||
DBG_LED_ON;
|
||||
for (w = DLED_ONTIME / 4; w; w--);
|
||||
led_off;
|
||||
DBG_LED_OFF;
|
||||
for (w = DLED_ONTIME / 4; w; w--);
|
||||
led_on;
|
||||
DBG_LED_ON;
|
||||
for (w = DLED_ONTIME / 4; w; w--);
|
||||
led_off;
|
||||
DBG_LED_OFF;
|
||||
for (w = DLED_ONTIME / 4; w; w--);
|
||||
n--;
|
||||
}
|
||||
@@ -84,9 +97,9 @@ void dled_print(uint32_t x, uint8_t long_pause)
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
led_on;
|
||||
DBG_LED_ON;
|
||||
for (w = DLED_ONTIME; w; w--);
|
||||
led_off;
|
||||
DBG_LED_OFF;
|
||||
for (w = DLED_ONTIME / 2; w; w--);
|
||||
n--;
|
||||
}
|
||||
@@ -102,11 +115,52 @@ void dled_print(uint32_t x, uint8_t long_pause)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BOOT_TRACING
|
||||
#ifdef DEBUG_BOOT_TRACING_ENABLE
|
||||
|
||||
volatile uint32_t debug_code;
|
||||
|
||||
void EIC_15_Handler()
|
||||
//These macros are for compile time substitution
|
||||
#define DEBUG_BOOT_TRACING_EXTINTn (DEBUG_BOOT_TRACING_PIN % _U_(0x10))
|
||||
#define DEBUG_BOOT_TRACING_EXTINTb (_U_(0x1) << DEBUG_BOOT_TRACING_EXTINTn)
|
||||
#define DEBUG_BOOT_TRACING_CONFIG_INDn (DEBUG_BOOT_TRACING_EXTINTn / _U_(0x8))
|
||||
#define DEBUG_BOOT_TRACING_CONFIG_SENSEn (DEBUG_BOOT_TRACING_EXTINTn % _U_(0x8))
|
||||
#define DEBUG_BOOT_TRACING_CONFIG_SENSEb (DEBUG_BOOT_TRACING_CONFIG_SENSEn * _U_(0x4))
|
||||
#define DEBUG_BOOT_TRACING_IRQn (EIC_0_IRQn + DEBUG_BOOT_TRACING_EXTINTn)
|
||||
|
||||
//These macros perform PORT+PIN definition translation to IRQn in the preprocessor
|
||||
#define PORTPIN_TO_IRQn_EXPAND(def) def
|
||||
#define PORTPIN_TO_IRQn_DEF(def) PORTPIN_TO_IRQn_EXPAND(def)
|
||||
#if DEBUG_BOOT_TRACING_PIN < 10
|
||||
#define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_ ## port ## 0 ## pin ## A_EIC_EXTINT_NUM)
|
||||
#else
|
||||
#define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_ ## port ## pin ## A_EIC_EXTINT_NUM)
|
||||
#endif
|
||||
#define PORTPIN_TO_IRQn(port, pin) PORTPIN_TO_IRQn_TODEF(port, pin)
|
||||
|
||||
//These macros perform function name output in the preprocessor
|
||||
#define DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq) void EIC_ ## irq ## _Handler(void)
|
||||
#define DEBUG_BOOT_TRACING_HANDLER(irq) DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq)
|
||||
|
||||
//To generate the function name of the IRQ handler catching boot tracing,
|
||||
// certain macros must be undefined, so save their current values to macro stack
|
||||
#pragma push_macro("PA")
|
||||
#pragma push_macro("PB")
|
||||
#pragma push_macro("_L_")
|
||||
|
||||
//Undefine / redefine pushed macros
|
||||
#undef PA
|
||||
#undef PB
|
||||
#undef _L_
|
||||
#define _L_(x) x
|
||||
|
||||
//Perform the work and output
|
||||
//Ex: PORT PB, PIN 31 = void EIC_15_Handler(void)
|
||||
DEBUG_BOOT_TRACING_HANDLER(PORTPIN_TO_IRQn(DEBUG_BOOT_TRACING_PORT, DEBUG_BOOT_TRACING_PIN))
|
||||
|
||||
//Restore macros
|
||||
#pragma pop_macro("PA")
|
||||
#pragma pop_macro("PB")
|
||||
#pragma pop_macro("_L_")
|
||||
{
|
||||
//This is only for non-functional keyboard troubleshooting and should be disabled after boot
|
||||
//Intention is to lock up the keyboard here with repeating debug led code
|
||||
@@ -120,13 +174,13 @@ void debug_code_init(void)
|
||||
{
|
||||
DBGC(DC_UNSET);
|
||||
|
||||
//Configure Ports for EIC on PB31
|
||||
PORT->Group[1].DIRCLR.reg = 1 << 31; //Input
|
||||
PORT->Group[1].OUTSET.reg = 1 << 31; //High
|
||||
PORT->Group[1].PINCFG[31].bit.INEN = 1; //Input Enable
|
||||
PORT->Group[1].PINCFG[31].bit.PULLEN = 1; //Pull Enable
|
||||
PORT->Group[1].PINCFG[31].bit.PMUXEN = 1; //Mux Enable
|
||||
PORT->Group[1].PMUX[15].bit.PMUXO = 0; //Mux A
|
||||
//Configure Ports for EIC
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Input
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTSET.reg = 1 << DEBUG_BOOT_TRACING_PIN; //High
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 1; //Input Enable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 1; //Pull Enable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 1; //Mux Enable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; //Mux A
|
||||
|
||||
//Enable CLK_EIC_APB
|
||||
MCLK->APBAMASK.bit.EIC_ = 1;
|
||||
@@ -134,25 +188,33 @@ void debug_code_init(void)
|
||||
//Configure EIC
|
||||
EIC->CTRLA.bit.SWRST = 1;
|
||||
while (EIC->SYNCBUSY.bit.SWRST) {}
|
||||
EIC->ASYNCH.reg = 1 << 15;
|
||||
EIC->INTENSET.reg = 1 << 15;
|
||||
EIC->CONFIG[1].bit.SENSE7 = 2;
|
||||
EIC->ASYNCH.reg = DEBUG_BOOT_TRACING_EXTINTb;
|
||||
EIC->INTENSET.reg = DEBUG_BOOT_TRACING_EXTINTb;
|
||||
EIC->CONFIG[DEBUG_BOOT_TRACING_CONFIG_INDn].reg |= (EIC_CONFIG_SENSE0_FALL_Val << DEBUG_BOOT_TRACING_CONFIG_SENSEb);
|
||||
EIC->CTRLA.bit.ENABLE = 1;
|
||||
while (EIC->SYNCBUSY.bit.ENABLE) {}
|
||||
|
||||
//Enable EIC IRQ
|
||||
NVIC_EnableIRQ(EIC_15_IRQn);
|
||||
NVIC_EnableIRQ(DEBUG_BOOT_TRACING_IRQn);
|
||||
}
|
||||
|
||||
void debug_code_disable(void)
|
||||
{
|
||||
//Disable EIC IRQ
|
||||
NVIC_DisableIRQ(EIC_15_IRQn);
|
||||
NVIC_DisableIRQ(DEBUG_BOOT_TRACING_IRQn);
|
||||
|
||||
//Disable EIC
|
||||
EIC->CTRLA.bit.ENABLE = 0;
|
||||
while (EIC->SYNCBUSY.bit.ENABLE) {}
|
||||
|
||||
//Default port configuration
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Input
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Low
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 0; //Input Disable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 0; //Pull Disable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 0; //Mux Disable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; //Mux A
|
||||
|
||||
//Disable CLK_EIC_APB
|
||||
MCLK->APBAMASK.bit.EIC_ = 0;
|
||||
}
|
||||
@@ -162,4 +224,4 @@ void debug_code_disable(void)
|
||||
void debug_code_init(void) {}
|
||||
void debug_code_disable(void) {}
|
||||
|
||||
#endif //DEBUG_BOOT_TRACING
|
||||
#endif //DEBUG_BOOT_TRACING_ENABLE
|
||||
|
||||
@@ -20,37 +20,65 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "samd51j18a.h"
|
||||
|
||||
//TODO: PS: Should bring these ports out to keyboard level configuration
|
||||
/* Debug LED */
|
||||
#if DEBUG_LED_ENABLE == 1
|
||||
#define DBG_LED_ENA PORT->Group[DEBUG_LED_PORT].DIRSET.reg = (1 << DEBUG_LED_PIN)
|
||||
#define DBG_LED_DIS PORT->Group[DEBUG_LED_PORT].DIRCLR.reg = (1 << DEBUG_LED_PIN)
|
||||
#define DBG_LED_ON PORT->Group[DEBUG_LED_PORT].OUTSET.reg = (1 << DEBUG_LED_PIN)
|
||||
#define DBG_LED_OFF PORT->Group[DEBUG_LED_PORT].OUTCLR.reg = (1 << DEBUG_LED_PIN)
|
||||
#else
|
||||
#define DBG_LED_ENA
|
||||
#define DBG_LED_DIS
|
||||
#define DBG_LED_ON
|
||||
#define DBG_LED_OFF
|
||||
#endif
|
||||
|
||||
//Debug LED PA27
|
||||
#define led_ena REG_PORT_DIRSET0 = 0x08000000 //PA27 Output
|
||||
#define led_on REG_PORT_OUTSET0 = 0x08000000 //PA27 High
|
||||
#define led_off REG_PORT_OUTCLR0 = 0x08000000 //PA27 Low
|
||||
/* Debug Port 1 */
|
||||
#if DEBUG_PORT1_ENABLE == 1
|
||||
#define DBG_1_ENA PORT->Group[DEBUG_PORT1_PORT].DIRSET.reg = (1 << DEBUG_PORT1_PIN)
|
||||
#define DBG_1_DIS PORT->Group[DEBUG_PORT1_PORT].DIRCLR.reg = (1 << DEBUG_PORT1_PIN)
|
||||
#define DBG_1_ON PORT->Group[DEBUG_PORT1_PORT].OUTSET.reg = (1 << DEBUG_PORT1_PIN)
|
||||
#define DBG_1_OFF PORT->Group[DEBUG_PORT1_PORT].OUTCLR.reg = (1 << DEBUG_PORT1_PIN)
|
||||
#else
|
||||
#define DBG_1_ENA
|
||||
#define DBG_1_DIS
|
||||
#define DBG_1_ON
|
||||
#define DBG_1_OFF
|
||||
#endif
|
||||
|
||||
//Debug Port PB30
|
||||
#define m15_ena REG_PORT_DIRSET1 = 0x40000000 //PB30 Output
|
||||
#define m15_on REG_PORT_OUTSET1 = 0x40000000 //PB30 High
|
||||
#define m15_off REG_PORT_OUTCLR1 = 0x40000000 //PB30 Low
|
||||
/* Debug Port 2 */
|
||||
#if DEBUG_PORT2_ENABLE == 1
|
||||
#define DBG_2_ENA PORT->Group[DEBUG_PORT2_PORT].DIRSET.reg = (1 << DEBUG_PORT2_PIN)
|
||||
#define DBG_2_DIS PORT->Group[DEBUG_PORT2_PORT].DIRCLR.reg = (1 << DEBUG_PORT2_PIN)
|
||||
#define DBG_2_ON PORT->Group[DEBUG_PORT2_PORT].OUTSET.reg = (1 << DEBUG_PORT2_PIN)
|
||||
#define DBG_2_OFF PORT->Group[DEBUG_PORT2_PORT].OUTCLR.reg = (1 << DEBUG_PORT2_PIN)
|
||||
#else
|
||||
#define DBG_2_ENA
|
||||
#define DBG_2_DIS
|
||||
#define DBG_2_ON
|
||||
#define DBG_2_OFF
|
||||
#endif
|
||||
|
||||
//Debug Port PB23
|
||||
#define m27_ena REG_PORT_DIRSET1 = 0x800000 //PB23 Output
|
||||
#define m27_on REG_PORT_OUTSET1 = 0x800000 //PB23 High
|
||||
#define m27_off REG_PORT_OUTCLR1 = 0x800000 //PB23 Low
|
||||
/* Debug Port 3 */
|
||||
#if DEBUG_PORT3_ENABLE == 1
|
||||
#define DBG_3_ENA PORT->Group[DEBUG_PORT3_PORT].DIRSET.reg = (1 << DEBUG_PORT3_PIN)
|
||||
#define DBG_3_DIS PORT->Group[DEBUG_PORT3_PORT].DIRCLR.reg = (1 << DEBUG_PORT3_PIN)
|
||||
#define DBG_3_ON PORT->Group[DEBUG_PORT3_PORT].OUTSET.reg = (1 << DEBUG_PORT3_PIN)
|
||||
#define DBG_3_OFF PORT->Group[DEBUG_PORT3_PORT].OUTCLR.reg = (1 << DEBUG_PORT3_PIN)
|
||||
#else
|
||||
#define DBG_3_ENA
|
||||
#define DBG_3_DIS
|
||||
#define DBG_3_ON
|
||||
#define DBG_3_OFF
|
||||
#endif
|
||||
|
||||
//Debug Port PB31
|
||||
#define m28_ena REG_PORT_DIRSET1 = 0x80000000 //PB31 Output
|
||||
#define m28_on REG_PORT_OUTSET1 = 0x80000000 //PB31 High
|
||||
#define m28_off REG_PORT_OUTCLR1 = 0x80000000 //PB31 Low
|
||||
|
||||
#define m15_loop(M15X) {uint8_t M15L=M15X; while(M15L--){m15_on;CLK_delay_us(1);m15_off;}}
|
||||
|
||||
void m15_print(uint32_t x);
|
||||
void dbg_print(uint32_t x);
|
||||
void dled_print(uint32_t x, uint8_t long_pause);
|
||||
|
||||
void debug_code_init(void);
|
||||
void debug_code_disable(void);
|
||||
|
||||
#ifdef DEBUG_BOOT_TRACING
|
||||
#ifdef DEBUG_BOOT_TRACING_ENABLE
|
||||
|
||||
#define DBGC(n) debug_code = n
|
||||
|
||||
@@ -190,6 +218,6 @@ enum debug_code_list {
|
||||
|
||||
#define DBGC(n) {}
|
||||
|
||||
#endif //DEBUG_BOOT_TRACING
|
||||
#endif //DEBUG_BOOT_TRACING_ENABLE
|
||||
|
||||
#endif //_D51_UTIL_H_
|
||||
|
||||
@@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
#if !defined(MD_BOOTLOADER) && defined(RGB_MATRIX_ENABLE)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -37,7 +37,7 @@ static uint8_t dma_sendbuf[I2C_DMA_MAX_SEND]; //Data being written to I2C
|
||||
|
||||
volatile uint8_t i2c_led_q_running;
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
#endif // !defined(MD_BOOTLOADER) && defined(RGB_MATRIX_ENABLE)
|
||||
|
||||
void i2c0_init(void)
|
||||
{
|
||||
@@ -112,7 +112,7 @@ void i2c0_stop(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
#if !defined(MD_BOOTLOADER) && defined(RGB_MATRIX_ENABLE)
|
||||
void i2c1_init(void)
|
||||
{
|
||||
DBGC(DC_I2C1_INIT_BEGIN);
|
||||
@@ -265,12 +265,12 @@ uint8_t I2C3733_Init_Control(void)
|
||||
//USB state machine will enable driver when communication is ready
|
||||
I2C3733_Control_Set(0);
|
||||
|
||||
CLK_delay_ms(1);
|
||||
wait_ms(1);
|
||||
|
||||
srdata.bit.IRST = 0;
|
||||
SPI_WriteSRData();
|
||||
sr_exp_data.bit.IRST = 0;
|
||||
SR_EXP_WriteData();
|
||||
|
||||
CLK_delay_ms(1);
|
||||
wait_ms(1);
|
||||
|
||||
DBGC(DC_I2C3733_INIT_CONTROL_COMPLETE);
|
||||
|
||||
@@ -357,8 +357,8 @@ void I2C3733_Control_Set(uint8_t state)
|
||||
{
|
||||
DBGC(DC_I2C3733_CONTROL_SET_BEGIN);
|
||||
|
||||
srdata.bit.SDB_N = (state == 1 ? 1 : 0);
|
||||
SPI_WriteSRData();
|
||||
sr_exp_data.bit.SDB_N = (state == 1 ? 1 : 0);
|
||||
SR_EXP_WriteData();
|
||||
|
||||
DBGC(DC_I2C3733_CONTROL_SET_COMPLETE);
|
||||
}
|
||||
@@ -489,7 +489,7 @@ uint8_t i2c_led_q_request_room(uint8_t request_size)
|
||||
|
||||
if (i2c_led_q_full >= 100) //Give the queue a chance to clear up
|
||||
{
|
||||
led_on;
|
||||
DBG_LED_ON;
|
||||
I2C_DMAC_LED_Init();
|
||||
i2c_led_q_init();
|
||||
return 1;
|
||||
@@ -583,4 +583,4 @@ uint8_t i2c_led_q_run(void)
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif //MD_BOOTLOADER
|
||||
#endif // !defined(MD_BOOTLOADER) && defined(RGB_MATRIX_ENABLE)
|
||||
|
||||
@@ -17,7 +17,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
#include "tmk_core/common/led.h"
|
||||
#include "rgb_matrix.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef USE_MASSDROP_CONFIGURATOR
|
||||
__attribute__((weak))
|
||||
led_instruction_t led_instructions[] = { { .end = 1 } };
|
||||
static void led_matrix_massdrop_config_override(int i);
|
||||
#endif // USE_MASSDROP_CONFIGURATOR
|
||||
|
||||
extern rgb_config_t rgb_matrix_config;
|
||||
extern rgb_counters_t g_rgb_counters;
|
||||
|
||||
void SERCOM1_0_Handler( void )
|
||||
{
|
||||
@@ -50,14 +61,17 @@ void DMAC_0_Handler( void )
|
||||
|
||||
issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
|
||||
|
||||
issi3733_led_t led_map[ISSI3733_LED_COUNT+1] = ISSI3733_LED_MAP;
|
||||
issi3733_led_t *lede = led_map + ISSI3733_LED_COUNT; //End pointer of mapping
|
||||
issi3733_led_t led_map[ISSI3733_LED_COUNT] = ISSI3733_LED_MAP;
|
||||
RGB led_buffer[ISSI3733_LED_COUNT];
|
||||
|
||||
uint8_t gcr_desired;
|
||||
uint8_t gcr_breathe;
|
||||
uint8_t gcr_use;
|
||||
uint8_t gcr_actual;
|
||||
uint8_t gcr_actual_last;
|
||||
#ifdef USE_MASSDROP_CONFIGURATOR
|
||||
uint8_t gcr_breathe;
|
||||
float breathe_mult;
|
||||
float pomod;
|
||||
#endif
|
||||
|
||||
#define ACT_GCR_NONE 0
|
||||
#define ACT_GCR_INC 1
|
||||
@@ -72,11 +86,14 @@ static uint8_t v_5v_cat_hit;
|
||||
void gcr_compute(void)
|
||||
{
|
||||
uint8_t action = ACT_GCR_NONE;
|
||||
uint8_t gcr_use = gcr_desired;
|
||||
|
||||
#ifdef USE_MASSDROP_CONFIGURATOR
|
||||
if (led_animation_breathing)
|
||||
{
|
||||
gcr_use = gcr_breathe;
|
||||
else
|
||||
gcr_use = gcr_desired;
|
||||
}
|
||||
#endif
|
||||
|
||||
//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)
|
||||
@@ -150,6 +167,7 @@ void gcr_compute(void)
|
||||
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
|
||||
if (led_animation_breathing == 1)
|
||||
@@ -159,12 +177,11 @@ void gcr_compute(void)
|
||||
// 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
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
led_disp_t disp;
|
||||
|
||||
void issi3733_prepare_arrays(void)
|
||||
{
|
||||
memset(issidrv,0,sizeof(issi3733_driver_t) * ISSI3733_DRIVER_COUNT);
|
||||
@@ -177,89 +194,189 @@ void issi3733_prepare_arrays(void)
|
||||
issidrv[i].addr = addrs[i];
|
||||
}
|
||||
|
||||
issi3733_led_t *cur = led_map;
|
||||
|
||||
while (cur < lede)
|
||||
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++)
|
||||
{
|
||||
//BYTE: 1 + (SW-1)*16 + (CS-1)
|
||||
cur->rgb.g = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swg-1)*16 + (cur->adr.cs-1));
|
||||
cur->rgb.r = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swr-1)*16 + (cur->adr.cs-1));
|
||||
cur->rgb.b = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swb-1)*16 + (cur->adr.cs-1));
|
||||
led_map[i].rgb.g = issidrv[led_map[i].adr.drv-1].pwm + 1 + ((led_map[i].adr.swg-1)*16 + (led_map[i].adr.cs-1));
|
||||
led_map[i].rgb.r = issidrv[led_map[i].adr.drv-1].pwm + 1 + ((led_map[i].adr.swr-1)*16 + (led_map[i].adr.cs-1));
|
||||
led_map[i].rgb.b = issidrv[led_map[i].adr.drv-1].pwm + 1 + ((led_map[i].adr.swb-1)*16 + (led_map[i].adr.cs-1));
|
||||
|
||||
//BYTE: 1 + (SW-1)*2 + (CS-1)/8
|
||||
//BIT: (CS-1)%8
|
||||
*(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swg-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
|
||||
*(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swr-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
|
||||
*(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swb-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
|
||||
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
|
||||
void disp_calc_extents(void)
|
||||
{
|
||||
issi3733_led_t *cur = led_map;
|
||||
|
||||
disp.left = 1e10;
|
||||
disp.right = -1e10;
|
||||
disp.top = -1e10;
|
||||
disp.bottom = 1e10;
|
||||
|
||||
while (cur < lede)
|
||||
{
|
||||
if (cur->x < disp.left) disp.left = cur->x;
|
||||
if (cur->x > disp.right) disp.right = cur->x;
|
||||
if (cur->y < disp.bottom) disp.bottom = cur->y;
|
||||
if (cur->y > disp.top) disp.top = cur->y;
|
||||
|
||||
cur++;
|
||||
}
|
||||
|
||||
disp.width = disp.right - disp.left;
|
||||
disp.height = disp.top - disp.bottom;
|
||||
}
|
||||
|
||||
void disp_pixel_setup(void)
|
||||
{
|
||||
issi3733_led_t *cur = led_map;
|
||||
|
||||
while (cur < lede)
|
||||
{
|
||||
cur->px = (cur->x - disp.left) / disp.width * 100;
|
||||
cur->py = (cur->y - disp.bottom) / disp.height * 100;
|
||||
*cur->rgb.r = 0;
|
||||
*cur->rgb.g = 0;
|
||||
*cur->rgb.b = 0;
|
||||
|
||||
cur++;
|
||||
*(issidrv[led_map[i].adr.drv-1].onoff + 1 + (led_map[i].adr.swg-1)*2+(led_map[i].adr.cs-1)/8) |= (1<<((led_map[i].adr.cs-1)%8));
|
||||
*(issidrv[led_map[i].adr.drv-1].onoff + 1 + (led_map[i].adr.swr-1)*2+(led_map[i].adr.cs-1)/8) |= (1<<((led_map[i].adr.cs-1)%8));
|
||||
*(issidrv[led_map[i].adr.drv-1].onoff + 1 + (led_map[i].adr.swb-1)*2+(led_map[i].adr.cs-1)/8) |= (1<<((led_map[i].adr.cs-1)%8));
|
||||
}
|
||||
}
|
||||
|
||||
void led_matrix_prepare(void)
|
||||
{
|
||||
disp_calc_extents();
|
||||
disp_pixel_setup();
|
||||
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++)
|
||||
{
|
||||
*led_map[i].rgb.r = 0;
|
||||
*led_map[i].rgb.g = 0;
|
||||
*led_map[i].rgb.b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t led_enabled;
|
||||
float led_animation_speed;
|
||||
uint8_t led_animation_direction;
|
||||
uint8_t led_animation_orientation;
|
||||
uint8_t led_animation_breathing;
|
||||
uint8_t led_animation_breathe_cur;
|
||||
uint8_t breathe_step;
|
||||
uint8_t breathe_dir;
|
||||
uint64_t led_next_run;
|
||||
void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
if (i < ISSI3733_LED_COUNT)
|
||||
{
|
||||
#ifdef USE_MASSDROP_CONFIGURATOR
|
||||
led_matrix_massdrop_config_override(i);
|
||||
#else
|
||||
led_buffer[i].r = r;
|
||||
led_buffer[i].g = g;
|
||||
led_buffer[i].b = b;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t led_animation_id;
|
||||
uint8_t led_lighting_mode;
|
||||
void led_set_all(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++)
|
||||
{
|
||||
led_set_one(i, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
issi3733_led_t *led_cur;
|
||||
uint8_t led_per_run = 15;
|
||||
float breathe_mult;
|
||||
float pomod;
|
||||
void init(void)
|
||||
{
|
||||
DBGC(DC_LED_MATRIX_INIT_BEGIN);
|
||||
|
||||
void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo, float pos) {
|
||||
issi3733_prepare_arrays();
|
||||
|
||||
led_matrix_prepare();
|
||||
|
||||
gcr_min_counter = 0;
|
||||
v_5v_cat_hit = 0;
|
||||
|
||||
DBGC(DC_LED_MATRIX_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// Wait for previous transfer to complete
|
||||
while (i2c_led_q_running) {}
|
||||
|
||||
// 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;
|
||||
*led_map[i].rgb.g = led_buffer[i].g;
|
||||
*led_map[i].rgb.b = led_buffer[i].b;
|
||||
}
|
||||
|
||||
#ifdef USE_MASSDROP_CONFIGURATOR
|
||||
breathe_mult = 1;
|
||||
|
||||
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;
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
//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 *= 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)
|
||||
{
|
||||
uint8_t kbled = keyboard_leds();
|
||||
if (kbled && rgb_matrix_config.enable)
|
||||
{
|
||||
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++)
|
||||
{
|
||||
if (
|
||||
#if USB_LED_NUM_LOCK_SCANCODE != 255
|
||||
(led_map[i].scan == USB_LED_NUM_LOCK_SCANCODE && (kbled & (1<<USB_LED_NUM_LOCK))) ||
|
||||
#endif //NUM LOCK
|
||||
#if USB_LED_CAPS_LOCK_SCANCODE != 255
|
||||
(led_map[i].scan == USB_LED_CAPS_LOCK_SCANCODE && (kbled & (1<<USB_LED_CAPS_LOCK))) ||
|
||||
#endif //CAPS LOCK
|
||||
#if USB_LED_SCROLL_LOCK_SCANCODE != 255
|
||||
(led_map[i].scan == USB_LED_SCROLL_LOCK_SCANCODE && (kbled & (1<<USB_LED_SCROLL_LOCK))) ||
|
||||
#endif //SCROLL LOCK
|
||||
#if USB_LED_COMPOSE_SCANCODE != 255
|
||||
(led_map[i].scan == USB_LED_COMPOSE_SCANCODE && (kbled & (1<<USB_LED_COMPOSE))) ||
|
||||
#endif //COMPOSE
|
||||
#if USB_LED_KANA_SCANCODE != 255
|
||||
(led_map[i].scan == USB_LED_KANA_SCANCODE && (kbled & (1<<USB_LED_KANA))) ||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const rgb_matrix_driver_t rgb_matrix_driver = {
|
||||
.init = init,
|
||||
.flush = flush,
|
||||
.set_color = led_set_one,
|
||||
.set_color_all = led_set_all
|
||||
};
|
||||
|
||||
/*==============================================================================
|
||||
= Legacy Lighting Support =
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef USE_MASSDROP_CONFIGURATOR
|
||||
// Ported from Massdrop QMK Github Repo
|
||||
|
||||
// TODO?: wire these up to keymap.c
|
||||
uint8_t led_animation_orientation = 0;
|
||||
uint8_t led_animation_direction = 0;
|
||||
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;
|
||||
|
||||
static void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo, float pos) {
|
||||
float po;
|
||||
|
||||
while (f->end != 1)
|
||||
@@ -314,141 +431,57 @@ void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo, float pos)
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
led_instruction_t led_instructions[] = { { .end = 1 } };
|
||||
|
||||
uint8_t highest_active_layer = 0;
|
||||
uint32_t temp_layer_state = 0;
|
||||
|
||||
__attribute__ ((weak))
|
||||
void led_matrix_run(void)
|
||||
static void led_matrix_massdrop_config_override(int i)
|
||||
{
|
||||
float ro;
|
||||
float go;
|
||||
float bo;
|
||||
float po;
|
||||
uint8_t led_this_run = 0;
|
||||
led_setup_t *f = (led_setup_t*)led_setups[led_animation_id];
|
||||
float ro = 0;
|
||||
float go = 0;
|
||||
float bo = 0;
|
||||
|
||||
if (led_cur == 0) //Denotes start of new processing cycle in the case of chunked processing
|
||||
{
|
||||
led_cur = led_map;
|
||||
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;
|
||||
|
||||
disp.frame += 1;
|
||||
uint8_t highest_active_layer = biton32(layer_state);
|
||||
|
||||
breathe_mult = 1;
|
||||
if (led_lighting_mode == LED_MODE_KEYS_ONLY && g_rgb_leds[i].matrix_co.raw == 0xff) {
|
||||
//Do not act on this LED
|
||||
} else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && g_rgb_leds[i].matrix_co.raw != 0xff) {
|
||||
//Do not act on this LED
|
||||
} else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY) {
|
||||
//Do not act on this LED (Only show indicators)
|
||||
} else {
|
||||
led_instruction_t* led_cur_instruction = led_instructions;
|
||||
while (!led_cur_instruction->end) {
|
||||
// Check if this applies to current layer
|
||||
if ((led_cur_instruction->flags & LED_FLAG_MATCH_LAYER) &&
|
||||
(led_cur_instruction->layer != highest_active_layer)) {
|
||||
goto next_iter;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
//Only needs to be calculated once per frame
|
||||
pomod = (float)(disp.frame % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
|
||||
pomod *= 100.0f;
|
||||
pomod = (uint32_t)pomod % 10000;
|
||||
pomod /= 100.0f;
|
||||
|
||||
highest_active_layer = 0;
|
||||
temp_layer_state = layer_state;
|
||||
|
||||
while (temp_layer_state >> 1 != 0) {
|
||||
highest_active_layer++;
|
||||
temp_layer_state = temp_layer_state >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (led_cur < lede && led_this_run < led_per_run)
|
||||
{
|
||||
ro = 0;
|
||||
go = 0;
|
||||
bo = 0;
|
||||
|
||||
if (led_animation_orientation)
|
||||
{
|
||||
po = led_cur->py;
|
||||
}
|
||||
else
|
||||
{
|
||||
po = led_cur->px;
|
||||
}
|
||||
|
||||
if (led_lighting_mode == LED_MODE_KEYS_ONLY && led_cur->scan == 255)
|
||||
{
|
||||
//Do not act on this LED
|
||||
}
|
||||
else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && led_cur->scan != 255)
|
||||
{
|
||||
//Do not act on this LED
|
||||
}
|
||||
else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY)
|
||||
{
|
||||
//Do not act on this LED (Only show indicators)
|
||||
}
|
||||
else
|
||||
{
|
||||
led_instruction_t *led_cur_instruction;
|
||||
led_cur_instruction = led_instructions;
|
||||
|
||||
//Act on LED
|
||||
if (led_cur_instruction->end) {
|
||||
// If no instructions, use normal pattern
|
||||
led_run_pattern(f, &ro, &go, &bo, po);
|
||||
} else {
|
||||
uint8_t skip;
|
||||
uint8_t modid = (led_cur->id - 1) / 32; //PS: Calculate which id# contains the led bit
|
||||
uint32_t modidbit = 1 << ((led_cur->id - 1) % 32); //PS: Calculate the bit within the id#
|
||||
uint32_t *bitfield; //PS: Will point to the id# within the current instruction
|
||||
|
||||
while (!led_cur_instruction->end) {
|
||||
skip = 0;
|
||||
|
||||
//PS: Check layer active first
|
||||
if (led_cur_instruction->flags & LED_FLAG_MATCH_LAYER) {
|
||||
if (led_cur_instruction->layer != highest_active_layer) {
|
||||
skip = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
if (led_cur_instruction->flags & LED_FLAG_MATCH_ID) {
|
||||
bitfield = &led_cur_instruction->id0 + modid; //PS: Add modid as offset to id0 address. *bitfield is now idX of the led id
|
||||
if (~(*bitfield) & modidbit) { //PS: Check if led bit is not set in idX
|
||||
skip = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
if (led_cur_instruction->flags & LED_FLAG_USE_RGB) {
|
||||
ro = led_cur_instruction->r;
|
||||
go = led_cur_instruction->g;
|
||||
bo = led_cur_instruction->b;
|
||||
} else if (led_cur_instruction->flags & LED_FLAG_USE_PATTERN) {
|
||||
led_run_pattern(led_setups[led_cur_instruction->pattern_id], &ro, &go, &bo, po);
|
||||
} else if (led_cur_instruction->flags & LED_FLAG_USE_ROTATE_PATTERN) {
|
||||
led_run_pattern(f, &ro, &go, &bo, po);
|
||||
}
|
||||
}
|
||||
|
||||
led_cur_instruction++;
|
||||
// Check if this applies to current index
|
||||
if (led_cur_instruction->flags & LED_FLAG_MATCH_ID) {
|
||||
uint8_t modid = i / 32; //Calculate which id# contains the led bit
|
||||
uint32_t modidbit = 1 << (i % 32); //Calculate the bit within the id#
|
||||
uint32_t *bitfield = &led_cur_instruction->id0 + modid; //Add modid as offset to id0 address. *bitfield is now idX of the led id
|
||||
if (~(*bitfield) & modidbit) { //Check if led bit is not set in idX
|
||||
goto next_iter;
|
||||
}
|
||||
}
|
||||
|
||||
if (led_cur_instruction->flags & LED_FLAG_USE_RGB) {
|
||||
ro = led_cur_instruction->r;
|
||||
go = led_cur_instruction->g;
|
||||
bo = led_cur_instruction->b;
|
||||
} else if (led_cur_instruction->flags & LED_FLAG_USE_PATTERN) {
|
||||
led_run_pattern(led_setups[led_cur_instruction->pattern_id], &ro, &go, &bo, po);
|
||||
} else if (led_cur_instruction->flags & LED_FLAG_USE_ROTATE_PATTERN) {
|
||||
led_run_pattern(led_setups[led_animation_id], &ro, &go, &bo, po);
|
||||
}
|
||||
|
||||
next_iter:
|
||||
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;
|
||||
@@ -459,126 +492,11 @@ void led_matrix_run(void)
|
||||
go *= breathe_mult;
|
||||
bo *= breathe_mult;
|
||||
}
|
||||
|
||||
*led_cur->rgb.r = (uint8_t)ro;
|
||||
*led_cur->rgb.g = (uint8_t)go;
|
||||
*led_cur->rgb.b = (uint8_t)bo;
|
||||
|
||||
#ifdef USB_LED_INDICATOR_ENABLE
|
||||
if (keyboard_leds())
|
||||
{
|
||||
uint8_t kbled = keyboard_leds();
|
||||
if (
|
||||
#if USB_LED_NUM_LOCK_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_NUM_LOCK_SCANCODE && kbled & (1<<USB_LED_NUM_LOCK)) ||
|
||||
#endif //NUM LOCK
|
||||
#if USB_LED_CAPS_LOCK_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_CAPS_LOCK_SCANCODE && kbled & (1<<USB_LED_CAPS_LOCK)) ||
|
||||
#endif //CAPS LOCK
|
||||
#if USB_LED_SCROLL_LOCK_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_SCROLL_LOCK_SCANCODE && kbled & (1<<USB_LED_SCROLL_LOCK)) ||
|
||||
#endif //SCROLL LOCK
|
||||
#if USB_LED_COMPOSE_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_COMPOSE_SCANCODE && kbled & (1<<USB_LED_COMPOSE)) ||
|
||||
#endif //COMPOSE
|
||||
#if USB_LED_KANA_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_KANA_SCANCODE && kbled & (1<<USB_LED_KANA)) ||
|
||||
#endif //KANA
|
||||
(0))
|
||||
{
|
||||
if (*led_cur->rgb.r > 127) *led_cur->rgb.r = 0;
|
||||
else *led_cur->rgb.r = 255;
|
||||
if (*led_cur->rgb.g > 127) *led_cur->rgb.g = 0;
|
||||
else *led_cur->rgb.g = 255;
|
||||
if (*led_cur->rgb.b > 127) *led_cur->rgb.b = 0;
|
||||
else *led_cur->rgb.b = 255;
|
||||
}
|
||||
}
|
||||
#endif //USB_LED_INDICATOR_ENABLE
|
||||
|
||||
led_cur++;
|
||||
led_this_run++;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t led_matrix_init(void)
|
||||
{
|
||||
DBGC(DC_LED_MATRIX_INIT_BEGIN);
|
||||
|
||||
issi3733_prepare_arrays();
|
||||
|
||||
led_matrix_prepare();
|
||||
|
||||
disp.frame = 0;
|
||||
led_next_run = 0;
|
||||
|
||||
led_enabled = 1;
|
||||
led_animation_id = 0;
|
||||
led_lighting_mode = LED_MODE_NORMAL;
|
||||
led_animation_speed = 4.0f;
|
||||
led_animation_direction = 0;
|
||||
led_animation_orientation = 0;
|
||||
led_animation_breathing = 0;
|
||||
led_animation_breathe_cur = BREATHE_MIN_STEP;
|
||||
breathe_step = 1;
|
||||
breathe_dir = 1;
|
||||
|
||||
gcr_min_counter = 0;
|
||||
v_5v_cat_hit = 0;
|
||||
|
||||
//Run led matrix code once for initial LED coloring
|
||||
led_cur = 0;
|
||||
rgb_matrix_init_user();
|
||||
led_matrix_run();
|
||||
|
||||
DBGC(DC_LED_MATRIX_INIT_COMPLETE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void rgb_matrix_init_user(void) {
|
||||
|
||||
}
|
||||
|
||||
#define LED_UPDATE_RATE 10 //ms
|
||||
|
||||
//led data processing can take time, so process data in chunks to free up the processor
|
||||
//this is done through led_cur and lede
|
||||
void led_matrix_task(void)
|
||||
{
|
||||
if (led_enabled)
|
||||
{
|
||||
//If an update may run and frame processing has completed
|
||||
if (CLK_get_ms() >= led_next_run && led_cur == lede)
|
||||
{
|
||||
uint8_t drvid;
|
||||
|
||||
led_next_run = CLK_get_ms() + LED_UPDATE_RATE; //Set next frame update time
|
||||
|
||||
//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();
|
||||
|
||||
led_cur = 0; //Signal next frame calculations may begin
|
||||
}
|
||||
}
|
||||
|
||||
//Process more data if not finished
|
||||
if (led_cur != lede)
|
||||
{
|
||||
//m15_off; //debug profiling
|
||||
led_matrix_run();
|
||||
//m15_on; //debug profiling
|
||||
}
|
||||
led_buffer[i].r = (uint8_t)ro;
|
||||
led_buffer[i].g = (uint8_t)go;
|
||||
led_buffer[i].b = (uint8_t)bo;
|
||||
}
|
||||
|
||||
#endif // USE_MASSDROP_CONFIGURATOR
|
||||
|
||||
@@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef _LED_MATRIX_H_
|
||||
#define _LED_MATRIX_H_
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
//From keyboard
|
||||
#include "config_led.h"
|
||||
|
||||
@@ -75,24 +77,20 @@ typedef struct issi3733_led_s {
|
||||
uint8_t scan; //Key scan code from wiring (set 0xFF if no key)
|
||||
} issi3733_led_t;
|
||||
|
||||
typedef struct led_disp_s {
|
||||
uint64_t frame;
|
||||
float left;
|
||||
float right;
|
||||
float top;
|
||||
float bottom;
|
||||
float width;
|
||||
float height;
|
||||
} led_disp_t;
|
||||
extern issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
|
||||
|
||||
uint8_t led_matrix_init(void);
|
||||
void rgb_matrix_init_user(void);
|
||||
extern uint8_t gcr_desired;
|
||||
extern uint8_t gcr_breathe;
|
||||
extern uint8_t gcr_actual;
|
||||
extern uint8_t gcr_actual_last;
|
||||
|
||||
#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
|
||||
void gcr_compute(void);
|
||||
|
||||
void led_matrix_indicators(void);
|
||||
|
||||
/*------------------------- Legacy Lighting Support ------------------------*/
|
||||
|
||||
#ifdef USE_MASSDROP_CONFIGURATOR
|
||||
|
||||
#define EF_NONE 0x00000000 //No effect
|
||||
#define EF_OVER 0x00000001 //Overwrite any previous color information with new
|
||||
@@ -113,13 +111,16 @@ typedef struct led_setup_s {
|
||||
uint8_t end; //Set to signal end of the setup
|
||||
} led_setup_t;
|
||||
|
||||
extern const uint8_t led_setups_count;
|
||||
extern void *led_setups[];
|
||||
|
||||
//LED Extra Instructions
|
||||
#define LED_FLAG_NULL 0x00
|
||||
#define LED_FLAG_MATCH_ID 0x01
|
||||
#define LED_FLAG_MATCH_LAYER 0x02
|
||||
#define LED_FLAG_USE_RGB 0x10
|
||||
#define LED_FLAG_USE_PATTERN 0x20
|
||||
#define LED_FLAG_USE_ROTATE_PATTERN 0x40
|
||||
#define LED_FLAG_NULL 0x00 //Matching and coloring not used (default)
|
||||
#define LED_FLAG_MATCH_ID 0x01 //Match on the ID of the LED (set id#'s to desired bit pattern, first LED is id 1)
|
||||
#define LED_FLAG_MATCH_LAYER 0x02 //Match on the current active layer (set layer to desired match layer)
|
||||
#define LED_FLAG_USE_RGB 0x10 //Use a specific RGB value (set r, g, b to desired output color values)
|
||||
#define LED_FLAG_USE_PATTERN 0x20 //Use a specific pattern ID (set pattern_id to desired output pattern)
|
||||
#define LED_FLAG_USE_ROTATE_PATTERN 0x40 //Use pattern the user has cycled to manually
|
||||
|
||||
typedef struct led_instruction_s {
|
||||
uint16_t flags; // Bitfield for LED instructions
|
||||
@@ -135,35 +136,23 @@ typedef struct led_instruction_s {
|
||||
uint8_t end;
|
||||
} led_instruction_t;
|
||||
|
||||
extern issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
|
||||
|
||||
extern uint8_t gcr_desired;
|
||||
extern uint8_t gcr_breathe;
|
||||
extern uint8_t gcr_actual;
|
||||
extern uint8_t gcr_actual_last;
|
||||
|
||||
extern uint8_t led_animation_id;
|
||||
extern uint8_t led_enabled;
|
||||
extern float led_animation_speed;
|
||||
extern uint8_t led_lighting_mode;
|
||||
extern uint8_t led_animation_direction;
|
||||
extern uint8_t led_animation_orientation;
|
||||
extern uint8_t led_animation_breathing;
|
||||
extern uint8_t led_animation_breathe_cur;
|
||||
extern uint8_t breathe_dir;
|
||||
extern const uint8_t led_setups_count;
|
||||
|
||||
extern void *led_setups[];
|
||||
extern led_instruction_t led_instructions[];
|
||||
|
||||
extern uint32_t layer_state;
|
||||
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 issi3733_led_t *led_cur;
|
||||
extern issi3733_led_t *lede;
|
||||
#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
|
||||
|
||||
void led_matrix_run(void);
|
||||
void led_matrix_task(void);
|
||||
|
||||
void gcr_compute(void);
|
||||
#endif // USE_MASSDROP_CONFIGURATOR
|
||||
|
||||
#endif //_LED_MATRIX_H_
|
||||
|
||||
123
tmk_core/protocol/arm_atsam/led_matrix_programs.c
Normal file
123
tmk_core/protocol/arm_atsam/led_matrix_programs.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright 2018 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/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_MASSDROP_CONFIGURATOR
|
||||
|
||||
#include "led_matrix.h"
|
||||
|
||||
//Teal <-> Salmon
|
||||
led_setup_t leds_teal_salmon[] = {
|
||||
{ .hs = 0, .he = 33, .rs = 24, .re = 24, .gs = 215, .ge = 215, .bs = 204, .be = 204, .ef = EF_NONE },
|
||||
{ .hs = 33, .he = 66, .rs = 24, .re = 255, .gs = 215, .ge = 114, .bs = 204, .be = 118, .ef = EF_NONE },
|
||||
{ .hs = 66, .he = 100, .rs = 255, .re = 255, .gs = 114, .ge = 114, .bs = 118, .be = 118, .ef = EF_NONE },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Yellow
|
||||
led_setup_t leds_yellow[] = {
|
||||
{ .hs = 0, .he = 100, .rs = 255, .re = 255, .gs = 255, .ge = 255, .bs = 0, .be = 0, .ef = EF_NONE },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Off
|
||||
led_setup_t leds_off[] = {
|
||||
{ .hs = 0, .he = 100, .rs = 0, .re = 0, .gs = 0, .ge = 0, .bs = 0, .be = 0, .ef = EF_NONE },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Red
|
||||
led_setup_t leds_red[] = {
|
||||
{ .hs = 0, .he = 100, .rs = 255, .re = 255, .gs = 0, .ge = 0, .bs = 0, .be = 0, .ef = EF_NONE },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Green
|
||||
led_setup_t leds_green[] = {
|
||||
{ .hs = 0, .he = 100, .rs = 0, .re = 0, .gs = 255, .ge = 255, .bs = 0, .be = 0, .ef = EF_NONE },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Blue
|
||||
led_setup_t leds_blue[] = {
|
||||
{ .hs = 0, .he = 100, .rs = 0, .re = 0, .gs = 0, .ge = 0, .bs = 255, .be = 255, .ef = EF_NONE },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//White
|
||||
led_setup_t leds_white[] = {
|
||||
{ .hs = 0, .he = 100, .rs = 255, .re = 255, .gs = 255, .ge = 255, .bs = 255, .be = 255, .ef = EF_NONE },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//White with moving red stripe
|
||||
led_setup_t leds_white_with_red_stripe[] = {
|
||||
{ .hs = 0, .he = 100, .rs = 255, .re = 255, .gs = 255, .ge = 255, .bs = 255, .be = 255, .ef = EF_NONE },
|
||||
{ .hs = 0, .he = 15, .rs = 0, .re = 0, .gs = 0, .ge = 255, .bs = 0, .be = 255, .ef = EF_SCR_R | EF_SUBTRACT },
|
||||
{ .hs = 15, .he = 30, .rs = 0, .re = 0, .gs = 255, .ge = 0, .bs = 255, .be = 0, .ef = EF_SCR_R | EF_SUBTRACT },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Black with moving red stripe
|
||||
led_setup_t leds_black_with_red_stripe[] = {
|
||||
{ .hs = 0, .he = 15, .rs = 0, .re = 255, .gs = 0, .ge = 0, .bs = 0, .be = 0, .ef = EF_SCR_R },
|
||||
{ .hs = 15, .he = 30, .rs = 255, .re = 0, .gs = 0, .ge = 0, .bs = 0, .be = 0, .ef = EF_SCR_R },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Rainbow no scrolling
|
||||
led_setup_t leds_rainbow_ns[] = {
|
||||
{ .hs = 0, .he = 16.67, .rs = 255, .re = 255, .gs = 0, .ge = 255, .bs = 0, .be = 0, .ef = EF_OVER },
|
||||
{ .hs = 16.67, .he = 33.33, .rs = 255, .re = 0, .gs = 255, .ge = 255, .bs = 0, .be = 0, .ef = EF_OVER },
|
||||
{ .hs = 33.33, .he = 50, .rs = 0, .re = 0, .gs = 255, .ge = 255, .bs = 0, .be = 255, .ef = EF_OVER },
|
||||
{ .hs = 50, .he = 66.67, .rs = 0, .re = 0, .gs = 255, .ge = 0, .bs = 255, .be = 255, .ef = EF_OVER },
|
||||
{ .hs = 66.67, .he = 83.33, .rs = 0, .re = 255, .gs = 0, .ge = 0, .bs = 255, .be = 255, .ef = EF_OVER },
|
||||
{ .hs = 83.33, .he = 100, .rs = 255, .re = 255, .gs = 0, .ge = 0, .bs = 255, .be = 0, .ef = EF_OVER },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Rainbow scrolling
|
||||
led_setup_t leds_rainbow_s[] = {
|
||||
{ .hs = 0, .he = 16.67, .rs = 255, .re = 255, .gs = 0, .ge = 255, .bs = 0, .be = 0, .ef = EF_OVER | EF_SCR_R },
|
||||
{ .hs = 16.67, .he = 33.33, .rs = 255, .re = 0, .gs = 255, .ge = 255, .bs = 0, .be = 0, .ef = EF_OVER | EF_SCR_R },
|
||||
{ .hs = 33.33, .he = 50, .rs = 0, .re = 0, .gs = 255, .ge = 255, .bs = 0, .be = 255, .ef = EF_OVER | EF_SCR_R },
|
||||
{ .hs = 50, .he = 66.67, .rs = 0, .re = 0, .gs = 255, .ge = 0, .bs = 255, .be = 255, .ef = EF_OVER | EF_SCR_R },
|
||||
{ .hs = 66.67, .he = 83.33, .rs = 0, .re = 255, .gs = 0, .ge = 0, .bs = 255, .be = 255, .ef = EF_OVER | EF_SCR_R },
|
||||
{ .hs = 83.33, .he = 100, .rs = 255, .re = 255, .gs = 0, .ge = 0, .bs = 255, .be = 0, .ef = EF_OVER | EF_SCR_R },
|
||||
{ .end = 1 },
|
||||
};
|
||||
|
||||
//Add new LED animations here using one from above as example
|
||||
//The last entry must be { .end = 1 }
|
||||
//Add the new animation name to the list below following its format
|
||||
|
||||
void *led_setups[] = {
|
||||
leds_rainbow_s,
|
||||
leds_rainbow_ns,
|
||||
leds_teal_salmon,
|
||||
leds_yellow,
|
||||
leds_red,
|
||||
leds_green,
|
||||
leds_blue,
|
||||
leds_white,
|
||||
leds_white_with_red_stripe,
|
||||
leds_black_with_red_stripe,
|
||||
leds_off
|
||||
};
|
||||
|
||||
const uint8_t led_setups_count = sizeof(led_setups) / sizeof(led_setups[0]);
|
||||
|
||||
#endif
|
||||
@@ -159,7 +159,7 @@ void send_consumer(uint16_t data)
|
||||
|
||||
void main_subtask_usb_state(void)
|
||||
{
|
||||
static uint32_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware
|
||||
static uint64_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware
|
||||
uint8_t fsmstate_now = USB->DEVICE.FSMSTATUS.reg; //Current state from hardware register
|
||||
|
||||
if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If USB SUSPENDED
|
||||
@@ -188,9 +188,9 @@ void main_subtask_usb_state(void)
|
||||
{
|
||||
if (fsmstate_on_delay == 0) //If ON delay timer is cleared
|
||||
{
|
||||
fsmstate_on_delay = CLK_get_ms() + 250; //Set ON delay timer
|
||||
fsmstate_on_delay = timer_read64() + 250; //Set ON delay timer
|
||||
}
|
||||
else if (CLK_get_ms() > 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
|
||||
@@ -203,25 +203,20 @@ void main_subtask_usb_state(void)
|
||||
}
|
||||
}
|
||||
|
||||
void main_subtask_led(void)
|
||||
{
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) return; //Only run LED tasks if USB is operating
|
||||
|
||||
led_matrix_task();
|
||||
}
|
||||
|
||||
void main_subtask_power_check(void)
|
||||
{
|
||||
static uint64_t next_5v_checkup = 0;
|
||||
|
||||
if (CLK_get_ms() > next_5v_checkup)
|
||||
if (timer_read64() > next_5v_checkup)
|
||||
{
|
||||
next_5v_checkup = CLK_get_ms() + 5;
|
||||
next_5v_checkup = timer_read64() + 5;
|
||||
|
||||
v_5v = adc_get(ADC_5V);
|
||||
v_5v_avg = 0.9 * v_5v_avg + 0.1 * v_5v;
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
gcr_compute();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,9 +224,9 @@ void main_subtask_usb_extra_device(void)
|
||||
{
|
||||
static uint64_t next_usb_checkup = 0;
|
||||
|
||||
if (CLK_get_ms() > next_usb_checkup)
|
||||
if (timer_read64() > next_usb_checkup)
|
||||
{
|
||||
next_usb_checkup = CLK_get_ms() + 10;
|
||||
next_usb_checkup = timer_read64() + 10;
|
||||
|
||||
USB_HandleExtraDevice();
|
||||
}
|
||||
@@ -240,15 +235,19 @@ void main_subtask_usb_extra_device(void)
|
||||
void main_subtasks(void)
|
||||
{
|
||||
main_subtask_usb_state();
|
||||
main_subtask_led();
|
||||
main_subtask_power_check();
|
||||
main_subtask_usb_extra_device();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
led_ena;
|
||||
m15_ena;
|
||||
DBG_LED_ENA;
|
||||
DBG_1_ENA;
|
||||
DBG_1_OFF;
|
||||
DBG_2_ENA;
|
||||
DBG_2_OFF;
|
||||
DBG_3_ENA;
|
||||
DBG_3_OFF;
|
||||
|
||||
debug_code_init();
|
||||
|
||||
@@ -256,9 +255,11 @@ int main(void)
|
||||
|
||||
ADC0_init();
|
||||
|
||||
SPI_Init();
|
||||
SR_EXP_Init();
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
i2c1_init();
|
||||
#endif // RGB_MATRIX_ENABLE
|
||||
|
||||
matrix_init();
|
||||
|
||||
@@ -274,11 +275,9 @@ int main(void)
|
||||
|
||||
while (USB2422_Port_Detect_Init() == 0) {}
|
||||
|
||||
led_off;
|
||||
m15_off;
|
||||
|
||||
led_matrix_init();
|
||||
DBG_LED_OFF;
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
while (I2C3733_Init_Control() != 1) {}
|
||||
while (I2C3733_Init_Drivers() != 1) {}
|
||||
|
||||
@@ -288,6 +287,7 @@ int main(void)
|
||||
|
||||
for (uint8_t drvid = 0; drvid < ISSI3733_DRIVER_COUNT; drvid++)
|
||||
I2C_LED_Q_ONOFF(drvid); //Queue data
|
||||
#endif // RGB_MATRIX_ENABLE
|
||||
|
||||
keyboard_setup();
|
||||
|
||||
@@ -321,9 +321,9 @@ int main(void)
|
||||
keyboard_task();
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
if (CLK_get_ms() > next_print)
|
||||
if (timer_read64() > next_print)
|
||||
{
|
||||
next_print = CLK_get_ms() + 250;
|
||||
next_print = timer_read64() + 250;
|
||||
//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);
|
||||
}
|
||||
|
||||
@@ -17,73 +17,70 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
|
||||
Srdata_t srdata;
|
||||
sr_exp_t sr_exp_data;
|
||||
|
||||
void SPI_WriteSRData(void)
|
||||
void SR_EXP_WriteData(void)
|
||||
{
|
||||
uint16_t timeout;
|
||||
SR_EXP_RCLK_LO;
|
||||
|
||||
SC2_RCLCK_LO;
|
||||
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.DRE)) { DBGC(DC_SPI_WRITE_DRE); }
|
||||
|
||||
timeout = 50000;
|
||||
while (!(SCSPI->SPI.INTFLAG.bit.DRE) && --timeout) { DBGC(DC_SPI_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); }
|
||||
|
||||
SCSPI->SPI.DATA.bit.DATA = srdata.reg & 0xFF; //Shift in bits 7-0
|
||||
timeout = 50000;
|
||||
while (!(SCSPI->SPI.INTFLAG.bit.TXC) && --timeout) { DBGC(DC_SPI_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); }
|
||||
|
||||
SCSPI->SPI.DATA.bit.DATA = (srdata.reg >> 8) & 0xFF; //Shift in bits 15-8
|
||||
timeout = 50000;
|
||||
while (!(SCSPI->SPI.INTFLAG.bit.TXC) && --timeout) { DBGC(DC_SPI_WRITE_TXC_2); }
|
||||
|
||||
SC2_RCLCK_HI;
|
||||
SR_EXP_RCLK_HI;
|
||||
}
|
||||
|
||||
void SPI_Init(void)
|
||||
void SR_EXP_Init(void)
|
||||
{
|
||||
uint32_t timeout;
|
||||
|
||||
DBGC(DC_SPI_INIT_BEGIN);
|
||||
|
||||
CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
|
||||
|
||||
PORT->Group[0].PMUX[6].bit.PMUXE = 2;
|
||||
PORT->Group[0].PMUX[6].bit.PMUXO = 2;
|
||||
PORT->Group[0].PINCFG[12].bit.PMUXEN = 1;
|
||||
PORT->Group[0].PINCFG[13].bit.PMUXEN = 1;
|
||||
//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
|
||||
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
|
||||
|
||||
//Configure Shift Registers
|
||||
SC2_DIRSET;
|
||||
SC2_RCLCK_HI;
|
||||
SC2_OE_DIS;
|
||||
//Initialize Shift Register
|
||||
SR_EXP_OE_N_DIS;
|
||||
SR_EXP_RCLK_HI;
|
||||
|
||||
SCSPI->SPI.CTRLA.bit.DORD = 1;
|
||||
SCSPI->SPI.CTRLA.bit.CPOL = 1;
|
||||
SCSPI->SPI.CTRLA.bit.CPHA = 1;
|
||||
SCSPI->SPI.CTRLA.bit.DIPO = 3;
|
||||
SCSPI->SPI.CTRLA.bit.MODE = 3; //master
|
||||
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
|
||||
|
||||
SCSPI->SPI.CTRLA.bit.ENABLE = 1;
|
||||
timeout = 50000;
|
||||
while (SCSPI->SPI.SYNCBUSY.bit.ENABLE && timeout--) { DBGC(DC_SPI_SYNC_ENABLING); }
|
||||
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); }
|
||||
|
||||
srdata.reg = 0;
|
||||
srdata.bit.HUB_CONNECT = 0;
|
||||
srdata.bit.HUB_RESET_N = 0;
|
||||
srdata.bit.S_UP = 0;
|
||||
srdata.bit.E_UP_N = 1;
|
||||
srdata.bit.S_DN1 = 1;
|
||||
srdata.bit.E_DN1_N = 1;
|
||||
srdata.bit.E_VBUS_1 = 0;
|
||||
srdata.bit.E_VBUS_2 = 0;
|
||||
srdata.bit.SRC_1 = 1;
|
||||
srdata.bit.SRC_2 = 1;
|
||||
srdata.bit.IRST = 1;
|
||||
srdata.bit.SDB_N = 0;
|
||||
SPI_WriteSRData();
|
||||
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 register output
|
||||
SC2_OE_ENA;
|
||||
//Enable Shift Register output
|
||||
SR_EXP_OE_N_ENA;
|
||||
|
||||
DBGC(DC_SPI_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
@@ -18,21 +18,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef _SPI_H_
|
||||
#define _SPI_H_
|
||||
|
||||
//TODO: PS: Should bring ports to keyboard configuration
|
||||
/* 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)
|
||||
#define SR_EXP_OE_N_ENA PORT->Group[SR_EXP_OE_N_PORT].OUTCLR.reg = (1 << SR_EXP_OE_N_PIN)
|
||||
#define SR_EXP_OE_N_DIS PORT->Group[SR_EXP_OE_N_PORT].OUTSET.reg = (1 << SR_EXP_OE_N_PIN)
|
||||
|
||||
#define SCSPI SERCOM2
|
||||
/* Determine bits to set for mux selection */
|
||||
#if SR_EXP_DATAOUT_PIN % 2 == 0
|
||||
#define SR_EXP_DATAOUT_MUX_SEL PMUXE
|
||||
#else
|
||||
#define SR_EXP_DATAOUT_MUX_SEL PMUXO
|
||||
#endif
|
||||
|
||||
#define P14_DIR 0x00004000 /* PIN14 DIR Bit */
|
||||
#define P14_OUT 0x00004000 /* PIN14 OUT Bit */
|
||||
#define P15_DIR 0x00008000 /* PIN15 DIR Bit */
|
||||
#define P15_OUT 0x00008000 /* PIN15 OUT Bit */
|
||||
|
||||
#define SC2_RCLCK_LO REG_PORT_OUTCLR1 = P14_OUT /* PB14 Low, SC2_RCLCK Low */
|
||||
#define SC2_RCLCK_HI REG_PORT_OUTSET1 = P14_OUT /* PB14 High, SC2_RCLCK High */
|
||||
#define SC2_OE_ENA REG_PORT_OUTCLR1 = P15_OUT /* PB15 Low, SC2_OE_N Low (Shift register enabled) */
|
||||
#define SC2_OE_DIS REG_PORT_OUTSET1 = P15_OUT /* PB15 High, SC2_OE_N High (Shift register disabled) */
|
||||
#define SC2_DIRSET REG_PORT_DIRSET1 = P14_DIR | P15_DIR; /* PB14 PB15 OUT */
|
||||
/* Determine bits to set for mux selection */
|
||||
#if SR_EXP_SCLK_PIN % 2 == 0
|
||||
#define SR_EXP_SCLK_MUX_SEL PMUXE
|
||||
#else
|
||||
#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 */
|
||||
@@ -53,11 +60,11 @@ typedef union {
|
||||
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 */
|
||||
} Srdata_t;
|
||||
} sr_exp_t;
|
||||
|
||||
extern Srdata_t srdata;
|
||||
extern sr_exp_t sr_exp_data;
|
||||
|
||||
void SPI_WriteSRData(void);
|
||||
void SPI_Init(void);
|
||||
void SR_EXP_WriteData(void);
|
||||
void SR_EXP_Init(void);
|
||||
|
||||
#endif //_SPI_H_
|
||||
|
||||
@@ -134,6 +134,7 @@
|
||||
* heuristics and inline the function no matter how big it thinks it
|
||||
* becomes.
|
||||
*/
|
||||
#if !defined(__always_inline)
|
||||
#if defined(__CC_ARM)
|
||||
# define __always_inline __forceinline
|
||||
#elif (defined __GNUC__)
|
||||
@@ -141,6 +142,7 @@
|
||||
#elif (defined __ICCARM__)
|
||||
# define __always_inline _Pragma("inline=forced")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def __no_inline
|
||||
|
||||
@@ -1227,9 +1227,9 @@ uint32_t cdc_tx_send_time_next;
|
||||
|
||||
void CDC_send(void)
|
||||
{
|
||||
while (CLK_get_ms() < cdc_tx_send_time_next);
|
||||
while (timer_read64() < cdc_tx_send_time_next);
|
||||
udi_cdc_tx_send(0);
|
||||
cdc_tx_send_time_next = CLK_get_ms() + CDC_SEND_INTERVAL;
|
||||
cdc_tx_send_time_next = timer_read64() + CDC_SEND_INTERVAL;
|
||||
}
|
||||
|
||||
uint32_t CDC_print(char *printbuf)
|
||||
@@ -1238,7 +1238,7 @@ uint32_t CDC_print(char *printbuf)
|
||||
char *buf = printbuf;
|
||||
char c;
|
||||
|
||||
if (CLK_get_ms() < 5000) return 0;
|
||||
if (timer_read64() < 5000) return 0;
|
||||
|
||||
while ((c = *buf++) != 0 && !(count >= MAX_PRINT))
|
||||
{
|
||||
@@ -1339,7 +1339,7 @@ void CDC_init(void)
|
||||
inbuf.count = 0;
|
||||
inbuf.lastcount = 0;
|
||||
printbuf[0] = 0;
|
||||
cdc_tx_send_time_next = CLK_get_ms() + CDC_SEND_INTERVAL;
|
||||
cdc_tx_send_time_next = timer_read64() + CDC_SEND_INTERVAL;
|
||||
}
|
||||
|
||||
#else //CDC line 62
|
||||
|
||||
@@ -109,9 +109,9 @@ UDC_DESC_STORAGE udi_hid_kbd_report_desc_t udi_hid_kbd_report_desc = {
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute)
|
||||
0x81, 0x01, // Input (Constant)
|
||||
0x19, 0x00, // Usage Minimum (0)
|
||||
0x29, 0x65, // Usage Maximum (101)
|
||||
0x29, 0xFF, // Usage Maximum (255)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x65, // Logical Maximum (101)
|
||||
0x25, 0xFF, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0x81, 0x00, // Input (Data, Array)
|
||||
|
||||
@@ -64,7 +64,7 @@ void USB_write2422_block(void)
|
||||
i2c0_transmit(USB2422_ADDR, dest, 34, 50000);
|
||||
SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
|
||||
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP); }
|
||||
CLK_delay_us(100);
|
||||
wait_us(100);
|
||||
}
|
||||
|
||||
DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE);
|
||||
@@ -77,7 +77,6 @@ void USB2422_init(void)
|
||||
Port *pport = PORT;
|
||||
Oscctrl *posc = OSCCTRL;
|
||||
Usb *pusb = USB;
|
||||
Srdata_t *pspi = &srdata;
|
||||
|
||||
DBGC(DC_USB2422_INIT_BEGIN);
|
||||
|
||||
@@ -132,11 +131,11 @@ void USB2422_init(void)
|
||||
|
||||
i2c0_init(); //IC2 clk must be high at USB2422 reset release time to signal SMB configuration
|
||||
|
||||
pspi->bit.HUB_CONNECT = 1; //connect signal
|
||||
pspi->bit.HUB_RESET_N = 1; //reset high
|
||||
SPI_WriteSRData();
|
||||
sr_exp_data.bit.HUB_CONNECT = 1; //connect signal
|
||||
sr_exp_data.bit.HUB_RESET_N = 1; //reset high
|
||||
SR_EXP_WriteData();
|
||||
|
||||
CLK_delay_us(100);
|
||||
wait_us(100);
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
@@ -150,17 +149,14 @@ void USB2422_init(void)
|
||||
|
||||
void USB_reset(void)
|
||||
{
|
||||
Srdata_t *pspi = &srdata;
|
||||
|
||||
DBGC(DC_USB_RESET_BEGIN);
|
||||
|
||||
//pulse reset for at least 1 usec
|
||||
pspi->bit.HUB_RESET_N = 0; //reset low
|
||||
SPI_WriteSRData();
|
||||
CLK_delay_us(1);
|
||||
pspi->bit.HUB_RESET_N = 1; //reset high to run
|
||||
SPI_WriteSRData();
|
||||
CLK_delay_us(1);
|
||||
sr_exp_data.bit.HUB_RESET_N = 0; //reset low
|
||||
SR_EXP_WriteData();
|
||||
wait_us(2);
|
||||
sr_exp_data.bit.HUB_RESET_N = 1; //reset high to run
|
||||
SR_EXP_WriteData();
|
||||
|
||||
DBGC(DC_USB_RESET_COMPLETE);
|
||||
}
|
||||
@@ -241,16 +237,16 @@ void USB_set_host_by_voltage(void)
|
||||
#ifndef MD_BOOTLOADER
|
||||
usb_extra_state = USB_EXTRA_STATE_UNKNOWN;
|
||||
#endif //MD_BOOTLOADER
|
||||
srdata.bit.SRC_1 = 1; //USBC-1 available for test
|
||||
srdata.bit.SRC_2 = 1; //USBC-2 available for test
|
||||
srdata.bit.E_UP_N = 1; //HOST disable
|
||||
srdata.bit.E_DN1_N = 1; //EXTRA disable
|
||||
srdata.bit.E_VBUS_1 = 0; //USBC-1 disable full power I/O
|
||||
srdata.bit.E_VBUS_2 = 0; //USBC-2 disable full power I/O
|
||||
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
|
||||
|
||||
SPI_WriteSRData();
|
||||
SR_EXP_WriteData();
|
||||
|
||||
CLK_delay_ms(250);
|
||||
wait_ms(250);
|
||||
|
||||
while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB_SET_HOST_5V_LOW_WAITING); }
|
||||
|
||||
@@ -262,37 +258,37 @@ void USB_set_host_by_voltage(void)
|
||||
|
||||
if (v_con_1 > v_con_2)
|
||||
{
|
||||
srdata.bit.S_UP = 0; //HOST to USBC-1
|
||||
srdata.bit.S_DN1 = 1; //EXTRA to USBC-2
|
||||
srdata.bit.SRC_1 = 1; //HOST on USBC-1
|
||||
srdata.bit.SRC_2 = 0; //EXTRA available on USBC-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
|
||||
|
||||
srdata.bit.E_VBUS_1 = 1; //USBC-1 enable full power I/O
|
||||
srdata.bit.E_VBUS_2 = 0; //USBC-2 disable full power I/O
|
||||
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
|
||||
|
||||
SPI_WriteSRData();
|
||||
SR_EXP_WriteData();
|
||||
|
||||
srdata.bit.E_UP_N = 0; //HOST enable
|
||||
sr_exp_data.bit.E_UP_N = 0; //HOST enable
|
||||
|
||||
SPI_WriteSRData();
|
||||
SR_EXP_WriteData();
|
||||
|
||||
usb_host_port = USB_HOST_PORT_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srdata.bit.S_UP = 1; //EXTRA to USBC-1
|
||||
srdata.bit.S_DN1 = 0; //HOST to USBC-2
|
||||
srdata.bit.SRC_1 = 0; //EXTRA available on USBC-1
|
||||
srdata.bit.SRC_2 = 1; //HOST on USBC-2
|
||||
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
|
||||
|
||||
srdata.bit.E_VBUS_1 = 0; //USBC-1 disable full power I/O
|
||||
srdata.bit.E_VBUS_2 = 1; //USBC-2 enable full power I/O
|
||||
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
|
||||
|
||||
SPI_WriteSRData();
|
||||
SR_EXP_WriteData();
|
||||
|
||||
srdata.bit.E_UP_N = 0; //HOST enable
|
||||
sr_exp_data.bit.E_UP_N = 0; //HOST enable
|
||||
|
||||
SPI_WriteSRData();
|
||||
SR_EXP_WriteData();
|
||||
|
||||
usb_host_port = USB_HOST_PORT_2;
|
||||
}
|
||||
@@ -316,27 +312,27 @@ uint8_t USB2422_Port_Detect_Init(void)
|
||||
|
||||
USB_set_host_by_voltage();
|
||||
|
||||
port_detect_retry_ms = CLK_get_ms() + PORT_DETECT_RETRY_INTERVAL;
|
||||
port_detect_retry_ms = timer_read64() + PORT_DETECT_RETRY_INTERVAL;
|
||||
|
||||
while (!USB_active())
|
||||
{
|
||||
tmod = CLK_get_ms() % PORT_DETECT_RETRY_INTERVAL;
|
||||
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) { led_on; }
|
||||
else { led_off; }
|
||||
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) { led_on; }
|
||||
else if (tmod > 700 && tmod < 800) { led_on; }
|
||||
else { led_off; }
|
||||
if (tmod > 500 && tmod < 600) { DBG_LED_ON; }
|
||||
else if (tmod > 700 && tmod < 800) { DBG_LED_ON; }
|
||||
else { DBG_LED_OFF; }
|
||||
}
|
||||
|
||||
if (CLK_get_ms() > port_detect_retry_ms)
|
||||
if (timer_read64() > port_detect_retry_ms)
|
||||
{
|
||||
DBGC(DC_PORT_DETECT_INIT_FAILED);
|
||||
return 0;
|
||||
@@ -357,20 +353,22 @@ void USB_ExtraSetState(uint8_t state)
|
||||
if (state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG)
|
||||
state = USB_EXTRA_STATE_DISABLED;
|
||||
|
||||
if (usb_host_port == USB_HOST_PORT_1) srdata.bit.E_VBUS_2 = state;
|
||||
else if (usb_host_port == USB_HOST_PORT_2) srdata.bit.E_VBUS_1 = state;
|
||||
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;
|
||||
|
||||
srdata.bit.E_DN1_N = !state;
|
||||
SPI_WriteSRData();
|
||||
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");
|
||||
if (led_animation_breathing) gcr_breathe = gcr_desired;
|
||||
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");
|
||||
|
||||
@@ -42,13 +42,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
{
|
||||
|
||||
CPU_PRESCALE(0);
|
||||
|
||||
// DDRD = _BV(PD5);
|
||||
// DDRB = _BV(PB0);
|
||||
|
||||
|
||||
// PORTD = _BV(PD5);
|
||||
// PORTB = _BV(PB0);
|
||||
|
||||
@@ -59,22 +59,23 @@ int main(void)
|
||||
// while (!usb_configured()) /* wait */
|
||||
|
||||
|
||||
keyboard_setup();
|
||||
|
||||
dprintf("Initializing keyboard...\n");
|
||||
keyboard_init();
|
||||
|
||||
|
||||
// This implementation is pretty simplistic... if the USB connection
|
||||
// is not configured, choose the Bluefruit, otherwise use USB
|
||||
// Definitely would prefer to have this driven by an input pin and make
|
||||
// it switch dynamically - BCG
|
||||
// if (!usb_configured()) {
|
||||
|
||||
|
||||
// // Send power to Bluefruit... Adafruit says it takes 27 mA, I think
|
||||
// // the pins should provide 40 mA, but just in case I switch the
|
||||
// // the pins should provide 40 mA, but just in case I switch the
|
||||
// // Bluefruit using a transistor - BCG
|
||||
// DDRB = _BV(PB6);
|
||||
// PORTB |= _BV(PB6);
|
||||
|
||||
|
||||
dprintf("Setting host driver to bluefruit...\n");
|
||||
host_set_driver(bluefruit_driver());
|
||||
|
||||
@@ -131,7 +132,7 @@ int main(void)
|
||||
// usb_remote_wakeup();
|
||||
// }
|
||||
// }
|
||||
// keyboard_task();
|
||||
// keyboard_task();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@@ -113,12 +113,14 @@ int main(void) {
|
||||
chSysInit();
|
||||
|
||||
#ifdef STM32_EEPROM_ENABLE
|
||||
EEPROM_init();
|
||||
EEPROM_Init();
|
||||
#endif
|
||||
|
||||
// TESTING
|
||||
// chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
|
||||
|
||||
keyboard_setup();
|
||||
|
||||
/* Init USB */
|
||||
init_usb_driver(&USB_DRIVER);
|
||||
|
||||
|
||||
@@ -533,8 +533,7 @@ bool adafruit_ble_enable_keyboard(void) {
|
||||
// Disable command echo
|
||||
static const char kEcho[] PROGMEM = "ATE=0";
|
||||
// Make the advertised name match the keyboard
|
||||
static const char kGapDevName[] PROGMEM =
|
||||
"AT+GAPDEVNAME=" STR(PRODUCT) " " STR(DESCRIPTION);
|
||||
static const char kGapDevName[] PROGMEM = "AT+GAPDEVNAME=" STR(PRODUCT);
|
||||
// Turn on keyboard support
|
||||
static const char kHidEnOn[] PROGMEM = "AT+BLEHIDEN=1";
|
||||
|
||||
|
||||
@@ -517,17 +517,16 @@ void EVENT_USB_Device_ControlRequest(void)
|
||||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return;
|
||||
}
|
||||
#ifdef KEYBOARD_SHARED_EP
|
||||
uint8_t report_id = REPORT_ID_KEYBOARD;
|
||||
if (keyboard_protocol) {
|
||||
report_id = Endpoint_Read_8();
|
||||
}
|
||||
if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
|
||||
|
||||
if (Endpoint_BytesInEndpoint() == 2) {
|
||||
uint8_t report_id = Endpoint_Read_8();
|
||||
|
||||
if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
|
||||
keyboard_led_stats = Endpoint_Read_8();
|
||||
}
|
||||
} else {
|
||||
keyboard_led_stats = Endpoint_Read_8();
|
||||
}
|
||||
#else
|
||||
keyboard_led_stats = Endpoint_Read_8();
|
||||
#endif
|
||||
|
||||
Endpoint_ClearOUT();
|
||||
Endpoint_ClearStatusStage();
|
||||
|
||||
@@ -15,9 +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 CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0xCAFE
|
||||
@@ -25,16 +23,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MANUFACTURER t.m.k.
|
||||
#define PRODUCT USB to USB keyboard converter
|
||||
|
||||
|
||||
#define DESCRIPTION Product from t.m.k. keyboard firmware project
|
||||
|
||||
|
||||
/* matrix size */
|
||||
#define MATRIX_ROWS 32
|
||||
#define MATRIX_COLS 8
|
||||
|
||||
|
||||
/* key combination for command */
|
||||
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -56,6 +56,7 @@ int main(void)
|
||||
#ifndef NO_UART
|
||||
uart_init(UART_BAUD_RATE);
|
||||
#endif
|
||||
keyboard_setup();
|
||||
|
||||
keyboard_init();
|
||||
host_set_driver(vusb_driver());
|
||||
|
||||
@@ -95,7 +95,7 @@ const PROGMEM int usbDescriptorStringDevice[] = {
|
||||
#if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN
|
||||
#undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
|
||||
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber)
|
||||
PROGMEM int usbDescriptorStringSerialNumber[] = {
|
||||
const PROGMEM int usbDescriptorStringSerialNumber[] = {
|
||||
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN),
|
||||
USB_CFG_SERIAL_NUMBER
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user