1
0

Upstream merge up to 02d44beb44

This commit is contained in:
jonathan.liu
2019-07-11 23:21:18 -07:00
parent a0fac849eb
commit 441b212c86
4854 changed files with 157576 additions and 41541 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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"

View File

@@ -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)

View File

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

View File

@@ -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

View File

@@ -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_

View File

@@ -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)

View File

@@ -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

View File

@@ -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_

View 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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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_

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

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

View File

@@ -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();
// }
// }

View File

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

View File

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

View File

@@ -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();

View File

@@ -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

View File

@@ -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());

View File

@@ -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
};