Massdrop keyboard support (#3780)

* Massdrop SAMD51

Massdrop SAMD51 keyboards initial project upload

* Removing relocated files

Removing files that were relocated and not deleted from previous location

* LED queue fix and cleaning

Cleaned some white space or comments.
Fix for LED I2C command queue.
Cleaned up interrupts.
Added debug function for printing numbers to scope through m15 line.

* Factory programmed serial usage

Ability to use factory programmed serial in hub and keyboard usb descriptors

* USB serial number and bugfix

Added support for factory programmed serial and usage.
Incorporated bootloader's conditional compiling to align project closer.
Fixed issue when USB device attempted to send before enabled.
General white space and comment cleanup.

* Project cleanup

Cleaned up project in terms of white space, commented code, and unecessary files.
NKRO keyboard is now using correct setreport although KBD was fine to use.
Fixed broken linkage to __xprintf for serial debug statements.

* Fix for extra keys

Fixed possible USB hang on extra keys report set missing

* I2C cleanup

I2C cleanup and file renames necessary for master branch merge

* Boot tracing and clocks cleanup

Added optional boot debug trace mode through debug LED codes.
General clock code cleanup.

* Relocate ARM/Atmel headers

Moved ARM/Atmel header folder from drivers to lib and made necessary makefile changes.

* Pull request changes

Pull request changes

* Keymap and compile flag fix

Keymap fix for momentary layer.
Potential compile flag fix for Travis CI failure.

* va_list include fix

Fix for va_list compile failure

* Include file case fixes

Fixes for include files with incorrect case

* ctrl and alt67 keyboard readme

Added ctrl and alt67 keyboard readme files
This commit is contained in:
patrickmt
2018-08-29 15:07:52 -04:00
committed by Jack Humbert
parent a6c770432f
commit 30680c6eb3
194 changed files with 73324 additions and 1 deletions

View File

@ -0,0 +1,26 @@
ARM_ATSAM_DIR = protocol/arm_atsam
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
SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c
SRC += $(ARM_ATSAM_DIR)/spi.c
SRC += $(ARM_ATSAM_DIR)/startup.c
SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c
SRC += $(ARM_ATSAM_DIR)/usb/spfssf.c
SRC += $(ARM_ATSAM_DIR)/usb/udc.c
SRC += $(ARM_ATSAM_DIR)/usb/udi_cdc.c
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid.c
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd.c
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd_desc.c
SRC += $(ARM_ATSAM_DIR)/usb/ui.c
SRC += $(ARM_ATSAM_DIR)/usb/usb2422.c
SRC += $(ARM_ATSAM_DIR)/usb/usb.c
SRC += $(ARM_ATSAM_DIR)/usb/usb_device_udd.c
SRC += $(ARM_ATSAM_DIR)/usb/usb_util.c
# Search Path
VPATH += $(TMK_DIR)/$(ARM_ATSAM_DIR)

View File

@ -0,0 +1,99 @@
/*
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/>.
*/
#include "arm_atsam_protocol.h"
uint16_t v_5v;
uint16_t v_5v_avg;
uint16_t v_con_1;
uint16_t v_con_2;
uint16_t v_con_1_boot;
uint16_t v_con_2_boot;
void ADC0_clock_init(void)
{
DBGC(DC_ADC0_CLOCK_INIT_BEGIN);
MCLK->APBDMASK.bit.ADC0_ = 1; //ADC0 Clock Enable
GCLK->PCHCTRL[ADC0_GCLK_ID].bit.GEN = GEN_OSC0; //Select generator clock
GCLK->PCHCTRL[ADC0_GCLK_ID].bit.CHEN = 1; //Enable peripheral clock
DBGC(DC_ADC0_CLOCK_INIT_COMPLETE);
}
void ADC0_init(void)
{
DBGC(DC_ADC0_INIT_BEGIN);
//MCU
PORT->Group[1].DIRCLR.reg = 1 << 0; //PB00 as input 5V
PORT->Group[1].DIRCLR.reg = 1 << 1; //PB01 as input CON2
PORT->Group[1].DIRCLR.reg = 1 << 2; //PB02 as input CON1
PORT->Group[1].PMUX[0].bit.PMUXE = 1; //PB00 mux select B ADC 5V
PORT->Group[1].PMUX[0].bit.PMUXO = 1; //PB01 mux select B ADC CON2
PORT->Group[1].PMUX[1].bit.PMUXE = 1; //PB02 mux select B ADC CON1
PORT->Group[1].PINCFG[0].bit.PMUXEN = 1; //PB01 mux ADC Enable 5V
PORT->Group[1].PINCFG[1].bit.PMUXEN = 1; //PB01 mux ADC Enable CON2
PORT->Group[1].PINCFG[2].bit.PMUXEN = 1; //PB02 mux ADC Enable CON1
//ADC
ADC0->CTRLA.bit.SWRST = 1;
while (ADC0->SYNCBUSY.bit.SWRST) { DBGC(DC_ADC0_SWRST_SYNCING_1); }
while (ADC0->CTRLA.bit.SWRST) { DBGC(DC_ADC0_SWRST_SYNCING_2); }
//Clock divide
ADC0->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV2_Val;
//Averaging
ADC0->AVGCTRL.bit.SAMPLENUM = ADC_AVGCTRL_SAMPLENUM_4_Val;
while (ADC0->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC0_AVGCTRL_SYNCING_1); }
if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_1_Val) ADC0->AVGCTRL.bit.ADJRES = 0;
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_2_Val) ADC0->AVGCTRL.bit.ADJRES = 1;
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_4_Val) ADC0->AVGCTRL.bit.ADJRES = 2;
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_8_Val) ADC0->AVGCTRL.bit.ADJRES = 3;
else ADC0->AVGCTRL.bit.ADJRES = 4;
while (ADC0->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC0_AVGCTRL_SYNCING_2); }
//Settling
ADC0->SAMPCTRL.bit.SAMPLEN = 45; //Sampling Time Length: 1-63, 1 ADC CLK per
while (ADC0->SYNCBUSY.bit.SAMPCTRL) { DBGC(DC_ADC0_SAMPCTRL_SYNCING_1); }
//Load factory calibration data
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;
//Enable
ADC0->CTRLA.bit.ENABLE = 1;
while (ADC0->SYNCBUSY.bit.ENABLE) { DBGC(DC_ADC0_ENABLE_SYNCING_1); }
DBGC(DC_ADC0_INIT_COMPLETE);
}
uint16_t adc_get(uint8_t muxpos)
{
ADC0->INPUTCTRL.bit.MUXPOS = muxpos;
while (ADC0->SYNCBUSY.bit.INPUTCTRL) {}
ADC0->SWTRIG.bit.START = 1;
while (ADC0->SYNCBUSY.bit.SWTRIG) {}
while (!ADC0->INTFLAG.bit.RESRDY) {}
return ADC0->RESULT.reg;
}

View File

@ -0,0 +1,37 @@
/*
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/>.
*/
#ifndef _ADC_H_
#define _ADC_H_
#define ADC_5V_START_LEVEL 2365
#define ADC_5V ADC_INPUTCTRL_MUXPOS_AIN12_Val
#define ADC_CON1 ADC_INPUTCTRL_MUXPOS_AIN14_Val
#define ADC_CON2 ADC_INPUTCTRL_MUXPOS_AIN13_Val
extern uint16_t v_5v;
extern uint16_t v_5v_avg;
extern uint16_t v_con_1;
extern uint16_t v_con_2;
extern uint16_t v_con_1_boot;
extern uint16_t v_con_2_boot;
void ADC0_clock_init(void);
void ADC0_init(void);
#endif //_ADC_H_

View File

@ -0,0 +1,45 @@
/*
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/>.
*/
#ifndef _ARM_ATSAM_PROTOCOL_H_
#define _ARM_ATSAM_PROTOCOL_H_
#include "samd51j18a.h"
#include "md_bootloader.h"
#include "d51_util.h"
#include "clks.h"
#include "adc.h"
#include "i2c_master.h"
#include "spi.h"
#include "./usb/usb2422.h"
#ifndef MD_BOOTLOADER
#include "main_arm_atsam.h"
#include "led_matrix.h"
#include "issi3733_driver.h"
#include "./usb/compiler.h"
#include "./usb/udc.h"
#include "./usb/spfssf.h"
#include "./usb/udi_cdc.h"
#endif //MD_BOOTLOADER
#endif //_ARM_ATSAM_PROTOCOL_H_

View File

@ -0,0 +1,439 @@
/*
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/>.
*/
#include "arm_atsam_protocol.h"
#include <string.h>
volatile clk_t system_clks;
volatile uint64_t ms_clk;
volatile uint8_t us_delay_done;
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};
#define USE_DPLL_IND 0
#define USE_DPLL_DEF GCLK_SOURCE_DPLL0
void CLK_oscctrl_init(void)
{
Oscctrl *posctrl = OSCCTRL;
Gclk *pgclk = GCLK;
DBGC(DC_CLK_OSC_INIT_BEGIN);
//default setup on por
system_clks.freq_dfll = FREQ_DFLL_DEFAULT;
system_clks.freq_gclk[0] = system_clks.freq_dfll;
//configure and startup 16MHz xosc0
posctrl->XOSCCTRL[0].bit.ENABLE = 0;
posctrl->XOSCCTRL[0].bit.STARTUP = 0xD;
posctrl->XOSCCTRL[0].bit.ENALC = 1;
posctrl->XOSCCTRL[0].bit.IMULT = 5;
posctrl->XOSCCTRL[0].bit.IPTAT = 3;
posctrl->XOSCCTRL[0].bit.ONDEMAND = 0;
posctrl->XOSCCTRL[0].bit.XTALEN = 1;
posctrl->XOSCCTRL[0].bit.ENABLE = 1;
while (posctrl->STATUS.bit.XOSCRDY0 == 0) { DBGC(DC_CLK_OSC_INIT_XOSC0_SYNC); }
system_clks.freq_xosc0 = FREQ_XOSC0;
//configure and startup DPLL
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ENABLE = 0;
while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_DISABLE); }
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.REFCLK = 2; //select XOSC0 (16MHz)
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.DIV = 7; //16 MHz / (2 * (7 + 1)) = 1 MHz
posctrl->Dpll[USE_DPLL_IND].DPLLRATIO.bit.LDR = PLL_RATIO; //1 MHz * (PLL_RATIO(47) + 1) = 48MHz
while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.DPLLRATIO) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_RATIO); }
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ONDEMAND = 0;
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ENABLE = 1;
while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_ENABLE); }
while (posctrl->Dpll[USE_DPLL_IND].DPLLSTATUS.bit.LOCK == 0) { DBGC(DC_CLK_OSC_INIT_DPLL_WAIT_LOCK); }
while (posctrl->Dpll[USE_DPLL_IND].DPLLSTATUS.bit.CLKRDY == 0) { DBGC(DC_CLK_OSC_INIT_DPLL_WAIT_CLKRDY); }
system_clks.freq_dpll[0] = (system_clks.freq_xosc0 / 2 / (posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.DIV + 1)) * (posctrl->Dpll[USE_DPLL_IND].DPLLRATIO.bit.LDR + 1);
//change gclk0 to DPLL
pgclk->GENCTRL[GEN_DPLL0].bit.SRC = USE_DPLL_DEF;
while (pgclk->SYNCBUSY.bit.GENCTRL0) { DBGC(DC_CLK_OSC_INIT_GCLK_SYNC_GENCTRL0); }
system_clks.freq_gclk[0] = system_clks.freq_dpll[0];
DBGC(DC_CLK_OSC_INIT_COMPLETE);
}
//configure for 1MHz (1 usec timebase)
//call CLK_set_gclk_freq(GEN_TC45, FREQ_TC45_DEFAULT);
uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq)
{
Gclk *pgclk = GCLK;
DBGC(DC_CLK_SET_GCLK_FREQ_BEGIN);
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_1); }
pgclk->GENCTRL[gclkn].bit.SRC = USE_DPLL_DEF;
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_2); }
pgclk->GENCTRL[gclkn].bit.DIV = (uint8_t)(system_clks.freq_dpll[0] / freq);
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_3); }
pgclk->GENCTRL[gclkn].bit.DIVSEL = 0;
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_4); }
pgclk->GENCTRL[gclkn].bit.GENEN = 1;
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_5); }
system_clks.freq_gclk[gclkn] = system_clks.freq_dpll[0] / pgclk->GENCTRL[gclkn].bit.DIV;
DBGC(DC_CLK_SET_GCLK_FREQ_COMPLETE);
return system_clks.freq_gclk[gclkn];
}
void CLK_init_osc(void)
{
uint8_t gclkn = GEN_OSC0;
Gclk *pgclk = GCLK;
DBGC(DC_CLK_INIT_OSC_BEGIN);
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_1); }
pgclk->GENCTRL[gclkn].bit.SRC = GCLK_SOURCE_XOSC0;
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_2); }
pgclk->GENCTRL[gclkn].bit.DIV = 1;
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_3); }
pgclk->GENCTRL[gclkn].bit.DIVSEL = 0;
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_4); }
pgclk->GENCTRL[gclkn].bit.GENEN = 1;
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_5); }
system_clks.freq_gclk[gclkn] = system_clks.freq_xosc0;
DBGC(DC_CLK_INIT_OSC_COMPLETE);
}
void CLK_reset_time(void)
{
Tc *ptc4 = TC4;
Tc *ptc0 = TC0;
ms_clk = 0;
DBGC(DC_CLK_RESET_TIME_BEGIN);
//stop counters
ptc4->COUNT16.CTRLA.bit.ENABLE = 0;
while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) {}
ptc0->COUNT32.CTRLA.bit.ENABLE = 0;
while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) {}
//zero counters
ptc4->COUNT16.COUNT.reg = 0;
while (ptc4->COUNT16.SYNCBUSY.bit.COUNT) {}
ptc0->COUNT32.COUNT.reg = 0;
while (ptc0->COUNT32.SYNCBUSY.bit.COUNT) {}
//start counters
ptc0->COUNT32.CTRLA.bit.ENABLE = 1;
while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) {}
ptc4->COUNT16.CTRLA.bit.ENABLE = 1;
while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) {}
DBGC(DC_CLK_RESET_TIME_COMPLETE);
}
void TC4_Handler()
{
if (TC4->COUNT16.INTFLAG.bit.MC0)
{
TC4->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0;
ms_clk++;
}
}
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;
DBGC(DC_CLK_ENABLE_TIMEBASE_BEGIN);
//gclk2 highspeed time base
CLK_set_gclk_freq(GEN_TC45, FREQ_TC45_DEFAULT);
CLK_init_osc();
//unmask TC4, sourcegclk2 to TC4
pmclk->APBCMASK.bit.TC4_ = 1;
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;
while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_DISABLE); }
ptc4->COUNT16.CTRLA.bit.SWRST = 1;
while (ptc4->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_1); }
while (ptc4->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_2); }
//CTRLA defaults
//CTRLB as default, counting up
ptc4->COUNT16.CTRLBCLR.reg = 5;
while (ptc4->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CLTRB); }
ptc4->COUNT16.CC[0].reg = 999;
while (ptc4->COUNT16.SYNCBUSY.bit.CC0) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CC0); }
//ptc4->COUNT16.DBGCTRL.bit.DBGRUN = 1;
//wave mode
ptc4->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match
//generate event for next stage
ptc4->COUNT16.EVCTRL.bit.MCEO0 = 1;
NVIC_EnableIRQ(TC4_IRQn);
ptc4->COUNT16.INTENSET.bit.MC0 = 1;
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;
pgclk->PCHCTRL[TC0_GCLK_ID].bit.CHEN = 1;
pmclk->APBAMASK.bit.TC1_ = 1;
pgclk->PCHCTRL[TC1_GCLK_ID].bit.GEN = GEN_TC45;
pgclk->PCHCTRL[TC1_GCLK_ID].bit.CHEN = 1;
//configure TC0
DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_BEGIN);
ptc0->COUNT32.CTRLA.bit.ENABLE = 0;
while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_DISABLE); }
ptc0->COUNT32.CTRLA.bit.SWRST = 1;
while (ptc0->COUNT32.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_1); }
while (ptc0->COUNT32.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_2); }
//CTRLA as default
ptc0->COUNT32.CTRLA.bit.MODE = 2; //32 bit mode
ptc0->COUNT32.EVCTRL.bit.TCEI = 1; //enable incoming events
ptc0->COUNT32.EVCTRL.bit.EVACT = 2 ; //count events
DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_COMPLETE);
DBGC(DC_CLK_ENABLE_TIMEBASE_EVSYS_BEGIN);
//configure event system
pmclk->APBBMASK.bit.EVSYS_ = 1;
pgclk->PCHCTRL[EVSYS_GCLK_ID_0].bit.GEN = GEN_TC45;
pgclk->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN = 1;
pevsys->USER[44].reg = EVSYS_ID_USER_PORT_EV_0; //TC0 will get event channel 0
pevsys->Channel[0].CHANNEL.bit.EDGSEL = EVSYS_CHANNEL_EDGSEL_RISING_EDGE_Val; //Rising edge
pevsys->Channel[0].CHANNEL.bit.PATH = EVSYS_CHANNEL_PATH_SYNCHRONOUS_Val; //Synchronous
pevsys->Channel[0].CHANNEL.bit.EVGEN = EVSYS_ID_GEN_TC4_MCX_0; //TC4 MC0
DBGC(DC_CLK_ENABLE_TIMEBASE_EVSYS_COMPLETE);
CLK_reset_time();
ADC0_clock_init();
DBGC(DC_CLK_ENABLE_TIMEBASE_COMPLETE);
return 0;
}
uint32_t CLK_get_ms(void)
{
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) {}
}
void CLK_delay_ms(uint64_t msec)
{
msec += CLK_get_ms();
while (msec > CLK_get_ms()) {}
}
void clk_enable_sercom_apbmask(int sercomn)
{
Mclk *pmclk = MCLK;
switch (sercomn)
{
case 0:
pmclk->APBAMASK.bit.SERCOM0_ = 1;
break;
case 1:
pmclk->APBAMASK.bit.SERCOM1_ = 1;
break;
case 2:
pmclk->APBBMASK.bit.SERCOM2_ = 1;
break;
case 3:
pmclk->APBBMASK.bit.SERCOM3_ = 1;
break;
default:
break;
}
}
//call CLK_oscctrl_init first
//call CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq)
{
DBGC(DC_CLK_SET_SPI_FREQ_BEGIN);
Gclk *pgclk = GCLK;
Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
clk_enable_sercom_apbmask(sercomn);
//all gclk0 for now
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
psercom->I2CM.CTRLA.bit.SWRST = 1;
while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
while (psercom->I2CM.CTRLA.bit.SWRST) {}
psercom->SPI.BAUD.reg = (uint8_t) (system_clks.freq_gclk[0]/2/freq-1);
system_clks.freq_spi = system_clks.freq_gclk[0]/2/(psercom->SPI.BAUD.reg+1);
system_clks.freq_sercom[sercomn] = system_clks.freq_spi;
DBGC(DC_CLK_SET_SPI_FREQ_COMPLETE);
return system_clks.freq_spi;
}
//call CLK_oscctrl_init first
//call CLK_set_i2c0_freq(CHAN_SERCOM_I2C0, FREQ_I2C0_DEFAULT);
uint32_t CLK_set_i2c0_freq(uint8_t sercomn, uint32_t freq)
{
DBGC(DC_CLK_SET_I2C0_FREQ_BEGIN);
Gclk *pgclk = GCLK;
Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
clk_enable_sercom_apbmask(sercomn);
//all gclk0 for now
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
psercom->I2CM.CTRLA.bit.SWRST = 1;
while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
while (psercom->I2CM.CTRLA.bit.SWRST) {}
psercom->I2CM.BAUD.bit.BAUD = (uint8_t) (system_clks.freq_gclk[0]/2/freq-1);
system_clks.freq_i2c0 = system_clks.freq_gclk[0]/2/(psercom->I2CM.BAUD.bit.BAUD+1);
system_clks.freq_sercom[sercomn] = system_clks.freq_i2c0;
DBGC(DC_CLK_SET_I2C0_FREQ_COMPLETE);
return system_clks.freq_i2c0;
}
//call CLK_oscctrl_init first
//call CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
uint32_t CLK_set_i2c1_freq(uint8_t sercomn, uint32_t freq)
{
DBGC(DC_CLK_SET_I2C1_FREQ_BEGIN);
Gclk *pgclk = GCLK;
Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
clk_enable_sercom_apbmask(sercomn);
//all gclk0 for now
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
psercom->I2CM.CTRLA.bit.SWRST = 1;
while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
while (psercom->I2CM.CTRLA.bit.SWRST) {}
psercom->I2CM.BAUD.bit.BAUD = (uint8_t) (system_clks.freq_gclk[0]/2/freq-10);
system_clks.freq_i2c1 = system_clks.freq_gclk[0]/2/(psercom->I2CM.BAUD.bit.BAUD+10);
system_clks.freq_sercom[sercomn] = system_clks.freq_i2c1;
DBGC(DC_CLK_SET_I2C1_FREQ_COMPLETE);
return system_clks.freq_i2c1;
}
void CLK_init(void)
{
DBGC(DC_CLK_INIT_BEGIN);
memset((void *)&system_clks,0,sizeof(system_clks));
CLK_oscctrl_init();
CLK_enable_timebase();
DBGC(DC_CLK_INIT_COMPLETE);
}

View File

@ -0,0 +1,90 @@
/*
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/>.
*/
#ifndef _CLKS_H_
#define _CLKS_H_
#ifndef MD_BOOTLOADER
//From keyboard
#include "config_led.h"
#include "config.h"
#endif //MD_BOOTLOADER
#define PLL_RATIO 47 //mcu frequency ((X+1)MHz)
#define FREQ_DFLL_DEFAULT 48000000 //DFLL frequency / usb clock
#define FREQ_SPI_DEFAULT 1000000 //spi to 595 shift regs
#define FREQ_I2C0_DEFAULT 100000 //i2c to hub
#define FREQ_I2C1_DEFAULT I2C_HZ //i2c to LED drivers
#define FREQ_TC45_DEFAULT 1000000 //1 usec resolution
//I2C1 Set ~Result PWM Time (2x Drivers)
// 1000000 1090000
// 900000 1000000 3.82ms
// 800000 860000
// 700000 750000
// 600000 630000
// 580000 615000 6.08ms
// 500000 522000
#define FREQ_XOSC0 16000000
#define CHAN_SERCOM_SPI 2 //shift regs
#define CHAN_SERCOM_I2C0 0 //hub
#define CHAN_SERCOM_I2C1 1 //led drivers
#define CHAN_SERCOM_UART 3 //debug util
//Generator clock channels
#define GEN_DPLL0 0
#define GEN_OSC0 1
#define GEN_TC45 2
#define SERCOM_COUNT 5
#define GCLK_COUNT 12
typedef struct clk_s {
uint32_t freq_dfll;
uint32_t freq_dpll[2];
uint32_t freq_sercom[SERCOM_COUNT];
uint32_t freq_gclk[GCLK_COUNT];
uint32_t freq_xosc0;
uint32_t freq_spi;
uint32_t freq_i2c0;
uint32_t freq_i2c1;
uint32_t freq_uart;
uint32_t freq_adc0;
} clk_t;
extern volatile clk_t system_clks;
extern volatile uint64_t ms_clk;
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);
void CLK_delay_ms(uint64_t msec);
uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq);
uint32_t CLK_set_i2c0_freq(uint8_t sercomn, uint32_t freq);
uint32_t CLK_set_i2c1_freq(uint8_t sercomn, uint32_t freq);
void CLK_init(void);
#endif // _CLKS_H_

View File

@ -0,0 +1,165 @@
#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)
{
int8_t t;
uint32_t n;
uint32_t p, p2;
if (x < 10) t = 0;
else if (x < 100) t = 1;
else if (x < 1000) t = 2;
else if (x < 10000) t = 3;
else if (x < 100000) t = 4;
else if (x < 1000000) t = 5;
else if (x < 10000000) t = 6;
else if (x < 100000000) t = 7;
else if (x < 1000000000) t = 8;
else t = 9;
while (t >= 0)
{
p2 = t;
p = 1;
while (p2--) p *= 10;
n = x / p;
x -= n * p;
while (n > 0)
{
m15_on;
n--;
m15_off;
}
//Will always end with an extra toggle
m15_on;
t--;
m15_off;
}
}
//Display unsigned 32-bit number through debug led
//Read as follows: 1230 = [*] [* *] [* * *] [**] (note zero is fast double flash)
#define DLED_ONTIME 600000
#define DLED_PAUSE 1000000
volatile uint32_t w;
void dled_print(uint32_t x, uint8_t long_pause)
{
int8_t t;
uint32_t n;
uint32_t p, p2;
if (x < 10) t = 0;
else if (x < 100) t = 1;
else if (x < 1000) t = 2;
else if (x < 10000) t = 3;
else if (x < 100000) t = 4;
else if (x < 1000000) t = 5;
else if (x < 10000000) t = 6;
else if (x < 100000000) t = 7;
else if (x < 1000000000) t = 8;
else t = 9;
while (t >= 0)
{
p2 = t;
p = 1;
while (p2--) p *= 10;
n = x / p;
x -= n * p;
if (!n)
{
led_on;
for (w = DLED_ONTIME / 4; w; w--);
led_off;
for (w = DLED_ONTIME / 4; w; w--);
led_on;
for (w = DLED_ONTIME / 4; w; w--);
led_off;
for (w = DLED_ONTIME / 4; w; w--);
n--;
}
else
{
while (n > 0)
{
led_on;
for (w = DLED_ONTIME; w; w--);
led_off;
for (w = DLED_ONTIME / 2; w; w--);
n--;
}
}
for (w = DLED_PAUSE; w; w--);
t--;
}
if (long_pause)
{
for (w = DLED_PAUSE * 4; w; w--);
}
}
#ifdef DEBUG_BOOT_TRACING
volatile uint32_t debug_code;
void EIC_15_Handler()
{
//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
while (1)
{
dled_print(debug_code, 1);
}
}
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
//Enable CLK_EIC_APB
MCLK->APBAMASK.bit.EIC_ = 1;
//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->CTRLA.bit.ENABLE = 1;
while (EIC->SYNCBUSY.bit.ENABLE) {}
//Enable EIC IRQ
NVIC_EnableIRQ(EIC_15_IRQn);
}
void debug_code_disable(void)
{
//Disable EIC IRQ
NVIC_DisableIRQ(EIC_15_IRQn);
//Disable EIC
EIC->CTRLA.bit.ENABLE = 0;
while (EIC->SYNCBUSY.bit.ENABLE) {}
//Disable CLK_EIC_APB
MCLK->APBAMASK.bit.EIC_ = 0;
}
#else
void debug_code_init(void) {}
void debug_code_disable(void) {}
#endif //DEBUG_BOOT_TRACING

View File

@ -0,0 +1,185 @@
/*
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/>.
*/
#ifndef _D51_UTIL_H_
#define _D51_UTIL_H_
#include "samd51j18a.h"
//TODO: PS: Should bring these ports out to keyboard level configuration
//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 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
#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 dled_print(uint32_t x, uint8_t long_pause);
void debug_code_init(void);
void debug_code_disable(void);
#ifdef DEBUG_BOOT_TRACING
#define DBGC(n) debug_code = n
extern volatile uint32_t debug_code;
enum debug_code_list {
DC_UNSET = 0,
DC_CLK_INIT_BEGIN,
DC_CLK_INIT_COMPLETE,
DC_CLK_SET_I2C1_FREQ_BEGIN,
DC_CLK_SET_I2C1_FREQ_COMPLETE,
DC_CLK_SET_I2C0_FREQ_BEGIN,
DC_CLK_SET_I2C0_FREQ_COMPLETE,
DC_CLK_SET_SPI_FREQ_BEGIN,
DC_CLK_SET_SPI_FREQ_COMPLETE,
DC_CLK_ENABLE_TIMEBASE_BEGIN,
DC_CLK_ENABLE_TIMEBASE_SYNC_ENABLE,
DC_CLK_ENABLE_TIMEBASE_SYNC_SWRST_1,
DC_CLK_ENABLE_TIMEBASE_SYNC_SWRST_2,
DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN,
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_DISABLE,
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_1,
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_2,
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CLTRB,
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CC0,
DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE,
DC_CLK_ENABLE_TIMEBASE_TC5_BEGIN,
DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_DISABLE,
DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_1,
DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_2,
DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_CLTRB,
DC_CLK_ENABLE_TIMEBASE_TC5_COMPLETE,
DC_CLK_ENABLE_TIMEBASE_TC0_BEGIN,
DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_DISABLE,
DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_1,
DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_2,
DC_CLK_ENABLE_TIMEBASE_TC0_COMPLETE,
DC_CLK_ENABLE_TIMEBASE_EVSYS_BEGIN,
DC_CLK_ENABLE_TIMEBASE_EVSYS_COMPLETE,
DC_CLK_ENABLE_TIMEBASE_COMPLETE,
DC_CLK_SET_GCLK_FREQ_BEGIN,
DC_CLK_SET_GCLK_FREQ_SYNC_1,
DC_CLK_SET_GCLK_FREQ_SYNC_2,
DC_CLK_SET_GCLK_FREQ_SYNC_3,
DC_CLK_SET_GCLK_FREQ_SYNC_4,
DC_CLK_SET_GCLK_FREQ_SYNC_5,
DC_CLK_SET_GCLK_FREQ_COMPLETE,
DC_CLK_INIT_OSC_BEGIN,
DC_CLK_INIT_OSC_SYNC_1,
DC_CLK_INIT_OSC_SYNC_2,
DC_CLK_INIT_OSC_SYNC_3,
DC_CLK_INIT_OSC_SYNC_4,
DC_CLK_INIT_OSC_SYNC_5,
DC_CLK_INIT_OSC_COMPLETE,
DC_CLK_RESET_TIME_BEGIN,
DC_CLK_RESET_TIME_COMPLETE,
DC_CLK_OSC_INIT_BEGIN,
DC_CLK_OSC_INIT_XOSC0_SYNC,
DC_CLK_OSC_INIT_DPLL_SYNC_DISABLE,
DC_CLK_OSC_INIT_DPLL_SYNC_RATIO,
DC_CLK_OSC_INIT_DPLL_SYNC_ENABLE,
DC_CLK_OSC_INIT_DPLL_WAIT_LOCK,
DC_CLK_OSC_INIT_DPLL_WAIT_CLKRDY,
DC_CLK_OSC_INIT_GCLK_SYNC_GENCTRL0,
DC_CLK_OSC_INIT_COMPLETE,
DC_SPI_INIT_BEGIN,
DC_SPI_WRITE_DRE,
DC_SPI_WRITE_TXC_1,
DC_SPI_WRITE_TXC_2,
DC_SPI_SYNC_ENABLING,
DC_SPI_INIT_COMPLETE,
DC_PORT_DETECT_INIT_BEGIN,
DC_PORT_DETECT_INIT_FAILED,
DC_PORT_DETECT_INIT_COMPLETE,
DC_USB_RESET_BEGIN,
DC_USB_RESET_COMPLETE,
DC_USB_SET_HOST_BY_VOLTAGE_BEGIN,
DC_USB_SET_HOST_5V_LOW_WAITING,
DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE,
DC_USB_CONFIGURE_BEGIN,
DC_USB_CONFIGURE_GET_SERIAL,
DC_USB_CONFIGURE_COMPLETE,
DC_USB_WRITE2422_BLOCK_BEGIN,
DC_USB_WRITE2422_BLOCK_SYNC_SYSOP,
DC_USB_WRITE2422_BLOCK_COMPLETE,
DC_ADC0_CLOCK_INIT_BEGIN,
DC_ADC0_CLOCK_INIT_COMPLETE,
DC_ADC0_INIT_BEGIN,
DC_ADC0_SWRST_SYNCING_1,
DC_ADC0_SWRST_SYNCING_2,
DC_ADC0_AVGCTRL_SYNCING_1,
DC_ADC0_AVGCTRL_SYNCING_2,
DC_ADC0_SAMPCTRL_SYNCING_1,
DC_ADC0_ENABLE_SYNCING_1,
DC_ADC0_INIT_COMPLETE,
DC_I2C0_INIT_BEGIN,
DC_I2C0_INIT_SYNC_ENABLING,
DC_I2C0_INIT_SYNC_SYSOP,
DC_I2C0_INIT_WAIT_IDLE,
DC_I2C0_INIT_COMPLETE,
DC_I2C1_INIT_BEGIN,
DC_I2C1_INIT_SYNC_ENABLING,
DC_I2C1_INIT_SYNC_SYSOP,
DC_I2C1_INIT_WAIT_IDLE,
DC_I2C1_INIT_COMPLETE,
DC_I2C3733_INIT_CONTROL_BEGIN,
DC_I2C3733_INIT_CONTROL_COMPLETE,
DC_I2C3733_INIT_DRIVERS_BEGIN,
DC_I2C3733_INIT_DRIVERS_COMPLETE,
DC_I2C_DMAC_LED_INIT_BEGIN,
DC_I2C_DMAC_LED_INIT_COMPLETE,
DC_I2C3733_CONTROL_SET_BEGIN,
DC_I2C3733_CONTROL_SET_COMPLETE,
DC_LED_MATRIX_INIT_BEGIN,
DC_LED_MATRIX_INIT_COMPLETE,
DC_USB2422_INIT_BEGIN,
DC_USB2422_INIT_WAIT_5V_LOW,
DC_USB2422_INIT_OSC_SYNC_DISABLING,
DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_1,
DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_2,
DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_3,
DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_4,
DC_USB2422_INIT_OSC_SYNC_DFLLMUL,
DC_USB2422_INIT_OSC_SYNC_ENABLING,
DC_USB2422_INIT_USB_SYNC_SWRST,
DC_USB2422_INIT_USB_WAIT_SWRST,
DC_USB2422_INIT_USB_SYNC_ENABLING,
DC_USB2422_INIT_COMPLETE,
DC_MAIN_UDC_START_BEGIN,
DC_MAIN_UDC_START_COMPLETE,
DC_MAIN_CDC_INIT_BEGIN,
DC_MAIN_CDC_INIT_COMPLETE,
/* Never change the order of error codes! Only add codes to end! */
};
#else
#define DBGC(n) {}
#endif //DEBUG_BOOT_TRACING
#endif //_D51_UTIL_H_

View File

@ -0,0 +1,585 @@
/*
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/>.
*/
#include "arm_atsam_protocol.h"
#ifndef MD_BOOTLOADER
#include <string.h>
//From keyboard
#include "config.h"
#include "config_led.h"
#include "matrix.h"
#define I2C_LED_USE_DMA 1 //Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers
static uint8_t i2c_led_q[I2C_Q_SIZE]; //I2C queue circular buffer
static uint8_t i2c_led_q_s; //Start of circular buffer
static uint8_t i2c_led_q_e; //End of circular buffer
static uint8_t i2c_led_q_full; //Queue full counter for reset
static uint8_t dma_sendbuf[I2C_DMA_MAX_SEND]; //Data being written to I2C
volatile uint8_t i2c_led_q_running;
#endif //MD_BOOTLOADER
void i2c0_init(void)
{
DBGC(DC_I2C0_INIT_BEGIN);
CLK_set_i2c0_freq(CHAN_SERCOM_I2C0, FREQ_I2C0_DEFAULT);
//MCU
PORT->Group[0].PMUX[4].bit.PMUXE = 2;
PORT->Group[0].PMUX[4].bit.PMUXO = 2;
PORT->Group[0].PINCFG[8].bit.PMUXEN = 1;
PORT->Group[0].PINCFG[9].bit.PMUXEN = 1;
//I2C
//Note: SW Reset handled in CLK_set_i2c0_freq clks.c
SERCOM0->I2CM.CTRLA.bit.MODE = 5; //Set master mode
SERCOM0->I2CM.CTRLA.bit.SPEED = 0; //Set to 1 for Fast-mode Plus (FM+) up to 1 MHz
SERCOM0->I2CM.CTRLA.bit.RUNSTDBY = 1; //Enabled
SERCOM0->I2CM.CTRLA.bit.ENABLE = 1; //Enable the device
while (SERCOM0->I2CM.SYNCBUSY.bit.ENABLE) { DBGC(DC_I2C0_INIT_SYNC_ENABLING); } //Wait for SYNCBUSY.ENABLE to clear
SERCOM0->I2CM.STATUS.bit.BUSSTATE = 1; //Force into IDLE state
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_I2C0_INIT_SYNC_SYSOP); }
while (SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1) { DBGC(DC_I2C0_INIT_WAIT_IDLE); } //Wait while not idle
DBGC(DC_I2C0_INIT_COMPLETE);
}
uint8_t i2c0_start(uint8_t address)
{
SERCOM0->I2CM.ADDR.bit.ADDR = address;
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {}
while (SERCOM0->I2CM.INTFLAG.bit.MB == 0) {}
while (SERCOM0->I2CM.STATUS.bit.RXNACK) {}
return 1;
}
uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)
{
if (!length) return 0;
i2c0_start(address);
while (length)
{
SERCOM0->I2CM.DATA.bit.DATA = *data;
while (SERCOM0->I2CM.INTFLAG.bit.MB == 0) {}
while (SERCOM0->I2CM.STATUS.bit.RXNACK) {}
data++;
length--;
}
i2c0_stop();
return 1;
}
void i2c0_stop(void)
{
if (SERCOM0->I2CM.STATUS.bit.CLKHOLD || SERCOM0->I2CM.INTFLAG.bit.MB == 1 || SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1)
{
SERCOM0->I2CM.CTRLB.bit.CMD = 3;
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP);
while (SERCOM0->I2CM.STATUS.bit.CLKHOLD);
while (SERCOM0->I2CM.INTFLAG.bit.MB);
while (SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1);
}
}
#ifndef MD_BOOTLOADER
void i2c1_init(void)
{
DBGC(DC_I2C1_INIT_BEGIN);
CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
/* MCU */
PORT->Group[0].PMUX[8].bit.PMUXE = 2;
PORT->Group[0].PMUX[8].bit.PMUXO = 2;
PORT->Group[0].PINCFG[16].bit.PMUXEN = 1;
PORT->Group[0].PINCFG[17].bit.PMUXEN = 1;
/* I2C */
//Note: SW Reset handled in CLK_set_i2c1_freq clks.c
SERCOM1->I2CM.CTRLA.bit.MODE = 5; //MODE: Set master mode (No sync)
SERCOM1->I2CM.CTRLA.bit.SPEED = 1; //SPEED: Fm+ up to 1MHz (No sync)
SERCOM1->I2CM.CTRLA.bit.RUNSTDBY = 1; //RUNSTBY: Enabled (No sync)
SERCOM1->I2CM.CTRLB.bit.SMEN = 1; //SMEN: Smart mode enabled (For DMA)(No sync)
NVIC_EnableIRQ(SERCOM1_0_IRQn);
SERCOM1->I2CM.INTENSET.bit.ERROR = 1;
SERCOM1->I2CM.CTRLA.bit.ENABLE = 1; //ENABLE: Enable the device (sync SYNCBUSY.ENABLE)
while (SERCOM1->I2CM.SYNCBUSY.bit.ENABLE) { DBGC(DC_I2C1_INIT_SYNC_ENABLING); } //Wait for SYNCBUSY.ENABLE to clear
SERCOM1->I2CM.STATUS.bit.BUSSTATE = 1; //BUSSTATE: Force into IDLE state (sync SYNCBUSY.SYSOP)
while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_I2C1_INIT_SYNC_SYSOP); }
while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1) { DBGC(DC_I2C1_INIT_WAIT_IDLE); } //Wait while not idle
DBGC(DC_I2C1_INIT_COMPLETE);
}
uint8_t i2c1_start(uint8_t address)
{
SERCOM1->I2CM.ADDR.bit.ADDR = address;
while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP) {}
while (SERCOM1->I2CM.INTFLAG.bit.MB == 0) {}
while (SERCOM1->I2CM.STATUS.bit.RXNACK) {}
return 1;
}
uint8_t i2c1_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)
{
if (!length) return 0;
i2c1_start(address);
while (length)
{
SERCOM1->I2CM.DATA.bit.DATA = *data;
while (SERCOM1->I2CM.INTFLAG.bit.MB == 0) {}
while (SERCOM1->I2CM.STATUS.bit.RXNACK) {}
data++;
length--;
}
i2c1_stop();
return 1;
}
void i2c1_stop(void)
{
if (SERCOM1->I2CM.STATUS.bit.CLKHOLD || SERCOM1->I2CM.INTFLAG.bit.MB == 1 || SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1)
{
SERCOM1->I2CM.CTRLB.bit.CMD = 3;
while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP);
while (SERCOM1->I2CM.STATUS.bit.CLKHOLD);
while (SERCOM1->I2CM.INTFLAG.bit.MB);
while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1);
}
}
void i2c_led_send_CRWL(uint8_t drvid)
{
uint8_t i2cdata[] = { ISSI3733_CMDRWL, ISSI3733_CMDRWL_WRITE_ENABLE_ONCE };
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
}
void i2c_led_select_page(uint8_t drvid, uint8_t pageno)
{
uint8_t i2cdata[] = { ISSI3733_CMDR, pageno };
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
}
void i2c_led_send_GCR(uint8_t drvid)
{
uint8_t i2cdata[] = { ISSI3733_GCCR, 0x00 };
if (gcr_actual > LED_GCR_MAX) gcr_actual = LED_GCR_MAX;
i2cdata[1] = gcr_actual;
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
}
void i2c_led_send_onoff(uint8_t drvid)
{
#if I2C_LED_USE_DMA != 1
if (!i2c_led_q_running)
{
#endif
i2c_led_send_CRWL(drvid);
i2c_led_select_page(drvid, 0);
#if I2C_LED_USE_DMA != 1
}
#endif
*issidrv[drvid].onoff = 0; //Force start location offset to zero
i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].onoff, ISSI3733_PG0_BYTES, 0);
}
void i2c_led_send_mode_op_gcr(uint8_t drvid, uint8_t mode, uint8_t operation)
{
uint8_t i2cdata[] = { ISSI3733_CR, mode | operation, gcr_actual};
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
}
void i2c_led_send_pur_pdr(uint8_t drvid, uint8_t pur, uint8_t pdr)
{
uint8_t i2cdata[] = { ISSI3733_SWYR_PUR, pur, pdr };
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
}
void i2c_led_send_pwm(uint8_t drvid)
{
#if I2C_LED_USE_DMA != 1
if (!i2c_led_q_running)
{
#endif
i2c_led_send_CRWL(drvid);
i2c_led_select_page(drvid, 0);
#if I2C_LED_USE_DMA != 1
}
#endif
*issidrv[drvid].pwm = 0; //Force start location offset to zero
i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].pwm, ISSI3733_PG1_BYTES, 0);
}
uint8_t I2C3733_Init_Control(void)
{
DBGC(DC_I2C3733_INIT_CONTROL_BEGIN);
srdata.bit.SDB_N = 1;
SPI_WriteSRData();
CLK_delay_ms(1);
srdata.bit.IRST = 0;
SPI_WriteSRData();
CLK_delay_ms(1);
DBGC(DC_I2C3733_INIT_CONTROL_COMPLETE);
return 1;
}
uint8_t I2C3733_Init_Drivers(void)
{
DBGC(DC_I2C3733_INIT_DRIVERS_BEGIN);
gcr_actual = ISSI3733_GCR_DEFAULT;
gcr_actual_last = gcr_actual;
if (gcr_actual > LED_GCR_MAX) gcr_actual = LED_GCR_MAX;
gcr_desired = gcr_actual;
//Set up master device
i2c_led_send_CRWL(0);
i2c_led_select_page(0, 3);
i2c_led_send_mode_op_gcr(0, ISSI3733_CR_SYNC_MASTER, ISSI3733_CR_SSD_NORMAL);
//Set up slave device
i2c_led_send_CRWL(1);
i2c_led_select_page(1, 3);
i2c_led_send_mode_op_gcr(1, ISSI3733_CR_SYNC_SLAVE, ISSI3733_CR_SSD_NORMAL);
i2c_led_send_CRWL(0);
i2c_led_select_page(0, 3);
i2c_led_send_pur_pdr(0, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
i2c_led_send_CRWL(1);
i2c_led_select_page(1, 3);
i2c_led_send_pur_pdr(1, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
DBGC(DC_I2C3733_INIT_DRIVERS_COMPLETE);
return 1;
}
void I2C_DMAC_LED_Init(void)
{
Dmac *dmac = DMAC;
DBGC(DC_I2C_DMAC_LED_INIT_BEGIN);
//Disable device
dmac->CTRL.bit.DMAENABLE = 0; //Disable DMAC
while (dmac->CTRL.bit.DMAENABLE) {} //Wait for disabled state in case of ongoing transfers
dmac->CTRL.bit.SWRST = 1; //Software Reset DMAC
while (dmac->CTRL.bit.SWRST) {} //Wait for software reset to complete
//Configure device
dmac->BASEADDR.reg = (uint32_t)&dmac_desc; //Set descriptor base address
dmac->WRBADDR.reg = (uint32_t)&dmac_desc_wb; //Set descriptor write back address
dmac->CTRL.reg |= 0x0f00; //Handle all priorities (LVL0-3)
//Disable channel
dmac->Channel[0].CHCTRLA.bit.ENABLE = 0; //Disable the channel
while (dmac->Channel[0].CHCTRLA.bit.ENABLE) {} //Wait for disabled state in case of ongoing transfers
dmac->Channel[0].CHCTRLA.bit.SWRST = 1; //Software Reset the channel
while (dmac->Channel[0].CHCTRLA.bit.SWRST) {} //Wait for software reset to complete
//Configure channel
dmac->Channel[0].CHCTRLA.bit.THRESHOLD = 0; //1BEAT
dmac->Channel[0].CHCTRLA.bit.BURSTLEN = 0; //SINGLE
dmac->Channel[0].CHCTRLA.bit.TRIGACT = 2; //BURST
dmac->Channel[0].CHCTRLA.bit.TRIGSRC = SERCOM1_DMAC_ID_TX; //Trigger source
dmac->Channel[0].CHCTRLA.bit.RUNSTDBY = 1; //Run in standby
NVIC_EnableIRQ(DMAC_0_IRQn);
dmac->Channel[0].CHINTENSET.bit.TCMPL = 1;
dmac->Channel[0].CHINTENSET.bit.TERR = 1;
//Enable device
dmac->CTRL.bit.DMAENABLE = 1; //Enable DMAC
while (dmac->CTRL.bit.DMAENABLE == 0) {} //Wait for enable state
DBGC(DC_I2C_DMAC_LED_INIT_COMPLETE);
}
//state = 1 enable
//state = 0 disable
void I2C3733_Control_Set(uint8_t state)
{
DBGC(DC_I2C3733_CONTROL_SET_BEGIN);
srdata.bit.SDB_N = (state == 1 ? 1 : 0);
SPI_WriteSRData();
DBGC(DC_I2C3733_CONTROL_SET_COMPLETE);
}
void i2c_led_desc_defaults(void)
{
dmac_desc.BTCTRL.bit.STEPSIZE = 0; //SRCINC used in favor for auto 1 inc
dmac_desc.BTCTRL.bit.STEPSEL = 0; //SRCINC used in favor for auto 1 inc
dmac_desc.BTCTRL.bit.DSTINC = 0; //The Destination Address Increment is disabled
dmac_desc.BTCTRL.bit.SRCINC = 1; //The Source Address Increment is enabled (Inc by 1)
dmac_desc.BTCTRL.bit.BEATSIZE = 0; //8-bit bus transfer
dmac_desc.BTCTRL.bit.BLOCKACT = 0; //Channel will be disabled if it is the last block transfer in the transaction
dmac_desc.BTCTRL.bit.EVOSEL = 0; //Event generation disabled
dmac_desc.BTCTRL.bit.VALID = 1; //Set dmac valid
}
void i2c_led_prepare_send_dma(uint8_t *data, uint8_t len)
{
i2c_led_desc_defaults();
dmac_desc.BTCNT.reg = len;
dmac_desc.SRCADDR.reg = (uint32_t)data + len;
dmac_desc.DSTADDR.reg = (uint32_t)&SERCOM1->I2CM.DATA.reg;
dmac_desc.DESCADDR.reg = 0;
}
void i2c_led_begin_dma(uint8_t drvid)
{
DMAC->Channel[0].CHCTRLA.bit.ENABLE = 1; //Enable the channel
SERCOM1->I2CM.ADDR.reg = (dmac_desc.BTCNT.reg << 16) | 0x2000 | issidrv[drvid].addr; //Begin transfer
}
void i2c_led_send_CRWL_dma(uint8_t drvid)
{
*(dma_sendbuf+0) = ISSI3733_CMDRWL;
*(dma_sendbuf+1) = ISSI3733_CMDRWL_WRITE_ENABLE_ONCE;
i2c_led_prepare_send_dma(dma_sendbuf, 2);
i2c_led_begin_dma(drvid);
}
void i2c_led_select_page_dma(uint8_t drvid, uint8_t pageno)
{
*(dma_sendbuf+0) = ISSI3733_CMDR;
*(dma_sendbuf+1) = pageno;
i2c_led_prepare_send_dma(dma_sendbuf, 2);
i2c_led_begin_dma(drvid);
}
void i2c_led_send_GCR_dma(uint8_t drvid)
{
*(dma_sendbuf+0) = ISSI3733_GCCR;
*(dma_sendbuf+1) = gcr_actual;
i2c_led_prepare_send_dma(dma_sendbuf, 2);
i2c_led_begin_dma(drvid);
}
void i2c_led_send_pwm_dma(uint8_t drvid)
{
//Note: This copies the CURRENT pwm buffer, which may be getting modified
memcpy(dma_sendbuf, issidrv[drvid].pwm, ISSI3733_PG1_BYTES);
*dma_sendbuf = 0; //Force start location offset to zero
i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG1_BYTES);
i2c_led_begin_dma(drvid);
}
void i2c_led_send_onoff_dma(uint8_t drvid)
{
//Note: This copies the CURRENT onoff buffer, which may be getting modified
memcpy(dma_sendbuf, issidrv[drvid].onoff, ISSI3733_PG0_BYTES);
*dma_sendbuf = 0; //Force start location offset to zero
i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG0_BYTES);
i2c_led_begin_dma(drvid);
}
void i2c_led_q_init(void)
{
memset(i2c_led_q, 0, I2C_Q_SIZE);
i2c_led_q_s = 0;
i2c_led_q_e = 0;
i2c_led_q_running = 0;
i2c_led_q_full = 0;
}
uint8_t i2c_led_q_isempty(void)
{
return i2c_led_q_s == i2c_led_q_e;
}
uint8_t i2c_led_q_size(void)
{
return (i2c_led_q_e - i2c_led_q_s) % I2C_Q_SIZE;
}
uint8_t i2c_led_q_available(void)
{
return I2C_Q_SIZE - i2c_led_q_size() - 1; //Never allow end to meet start
}
void i2c_led_q_add(uint8_t cmd)
{
//WARNING: Always request room before adding commands!
//Assign command
i2c_led_q[i2c_led_q_e] = cmd;
i2c_led_q_e = (i2c_led_q_e + 1) % I2C_Q_SIZE; //Move end up one or wrap
}
void i2c_led_q_s_advance(void)
{
i2c_led_q_s = (i2c_led_q_s + 1) % I2C_Q_SIZE; //Move start up one or wrap
}
//Always request room before adding commands
//PS: In case the queue somehow gets filled, it will reset if it can not clear up
//PS: Could only get this to happen through unrealistic timings to overload the I2C bus
uint8_t i2c_led_q_request_room(uint8_t request_size)
{
if (request_size > i2c_led_q_available())
{
i2c_led_q_full++;
if (i2c_led_q_full >= 100) //Give the queue a chance to clear up
{
led_on;
I2C_DMAC_LED_Init();
i2c_led_q_init();
return 1;
}
return 0;
}
i2c_led_q_full = 0;
return 1;
}
uint8_t i2c_led_q_run(void)
{
if (i2c_led_q_isempty())
{
i2c_led_q_running = 0;
return 0;
}
if (i2c_led_q_running) return 1;
i2c_led_q_running = 1;
#if I2C_LED_USE_DMA != 1
while (!i2c_led_q_isempty())
{
#endif
//run command
if (i2c_led_q[i2c_led_q_s] == I2C_Q_CRWL)
{
i2c_led_q_s_advance();
uint8_t drvid = i2c_led_q[i2c_led_q_s];
#if I2C_LED_USE_DMA == 1
i2c_led_send_CRWL_dma(drvid);
#else
i2c_led_send_CRWL(drvid);
#endif
}
else if (i2c_led_q[i2c_led_q_s] == I2C_Q_PAGE_SELECT)
{
i2c_led_q_s_advance();
uint8_t drvid = i2c_led_q[i2c_led_q_s];
i2c_led_q_s_advance();
uint8_t page = i2c_led_q[i2c_led_q_s];
#if I2C_LED_USE_DMA == 1
i2c_led_select_page_dma(drvid, page);
#else
i2c_led_select_page(drvid, page);
#endif
}
else if (i2c_led_q[i2c_led_q_s] == I2C_Q_PWM)
{
i2c_led_q_s_advance();
uint8_t drvid = i2c_led_q[i2c_led_q_s];
#if I2C_LED_USE_DMA == 1
i2c_led_send_pwm_dma(drvid);
#else
i2c_led_send_pwm(drvid);
#endif
}
else if (i2c_led_q[i2c_led_q_s] == I2C_Q_GCR)
{
i2c_led_q_s_advance();
uint8_t drvid = i2c_led_q[i2c_led_q_s];
#if I2C_LED_USE_DMA == 1
i2c_led_send_GCR_dma(drvid);
#else
i2c_led_send_GCR(drvid);
#endif
}
else if (i2c_led_q[i2c_led_q_s] == I2C_Q_ONOFF)
{
i2c_led_q_s_advance();
uint8_t drvid = i2c_led_q[i2c_led_q_s];
#if I2C_LED_USE_DMA == 1
i2c_led_send_onoff_dma(drvid);
#else
i2c_led_send_onoff(drvid);
#endif
}
i2c_led_q_s_advance(); //Advance last run command or if the command byte was not serviced
#if I2C_LED_USE_DMA != 1
}
i2c_led_q_running = 0;
#endif
return 1;
}
#endif //MD_BOOTLOADER

View File

@ -0,0 +1,108 @@
/*
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/>.
*/
#ifndef _I2C_MASTER_H_
#define _I2C_MASTER_H_
#ifndef MD_BOOTLOADER
#include "samd51j18a.h"
#include "issi3733_driver.h"
#include "config.h"
__attribute__((__aligned__(16)))
DmacDescriptor dmac_desc;
__attribute__((__aligned__(16)))
DmacDescriptor dmac_desc_wb;
uint8_t I2C3733_Init_Control(void);
uint8_t I2C3733_Init_Drivers(void);
void I2C3733_Control_Set(uint8_t state);
void I2C_DMAC_LED_Init(void);
#define I2C_Q_SIZE 100
#define I2C_Q_NA 100
#define I2C_Q_CRWL 101
#define I2C_Q_PAGE_SELECT 102
#define I2C_Q_PWM 103
#define I2C_Q_GCR 104
#define I2C_Q_ONOFF 105
#define I2C_DMA_MAX_SEND 255
extern volatile uint8_t i2c_led_q_running;
#define I2C_LED_Q_PWM(a) { \
if (i2c_led_q_request_room(7)) \
{ \
i2c_led_q_add(I2C_Q_CRWL); \
i2c_led_q_add(a); \
i2c_led_q_add(I2C_Q_PAGE_SELECT); \
i2c_led_q_add(a); \
i2c_led_q_add(ISSI3733_PG_PWM); \
i2c_led_q_add(I2C_Q_PWM); \
i2c_led_q_add(a); \
} \
}
#define I2C_LED_Q_GCR(a) { \
if (i2c_led_q_request_room(7)) \
{ \
i2c_led_q_add(I2C_Q_CRWL); \
i2c_led_q_add(a); \
i2c_led_q_add(I2C_Q_PAGE_SELECT); \
i2c_led_q_add(a); \
i2c_led_q_add(ISSI3733_PG_FN); \
i2c_led_q_add(I2C_Q_GCR); \
i2c_led_q_add(a); \
} \
}
#define I2C_LED_Q_ONOFF(a) { \
if (i2c_led_q_request_room(7)) \
{ \
i2c_led_q_add(I2C_Q_CRWL); \
i2c_led_q_add(a); \
i2c_led_q_add(I2C_Q_PAGE_SELECT); \
i2c_led_q_add(a); \
i2c_led_q_add(ISSI3733_PG_ONOFF); \
i2c_led_q_add(I2C_Q_ONOFF); \
i2c_led_q_add(a); \
} \
}
void i2c_led_q_init(void);
void i2c_led_q_add(uint8_t cmd);
void i2c_led_q_s_advance(void);
uint8_t i2c_led_q_size(void);
uint8_t i2c_led_q_request_room(uint8_t request_size);
uint8_t i2c_led_q_run(void);
void i2c1_init(void);
uint8_t i2c1_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
void i2c1_stop(void);
#endif //MD_BOOTLOADER
void i2c0_init(void);
uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
void i2c0_stop(void);
#endif // _I2C_MASTER_H_

View File

@ -0,0 +1,201 @@
/*
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/>.
*/
#ifndef _ISSI3733_DRIVER_H_
#define _ISSI3733_DRIVER_H_
//ISII3733 Registers
#define ISSI3733_CMDR 0xFD //Command Register (Write Only)
#define ISSI3733_CMDRWL 0xFE //Command Register Write Lock (Read/Write)
#define ISSI3733_CMDRWL_WRITE_DISABLE 0x00 //Lock register
#define ISSI3733_CMDRWL_WRITE_ENABLE_ONCE 0xC5 //Enable one write to register then reset to locked
#define ISSI3733_IMR 0xF0 //Interrupt Mask Register (Write Only)
#define ISSI3733_IMR_IAC_ON 0x08 //Auto Clear Interrupt Bit - Interrupt auto clear when INTB stay low exceeds 8ms
#define ISSI3733_IMR_IAB_ON 0x04 //Auto Breath Interrupt Bit - Enable auto breath loop finish interrupt
#define ISSI3733_IMR_IS_ON 0x02 //Dot Short Interrupt Bit - Enable dot short interrupt
#define ISSI3733_IMR_IO_ON 0x01 //Dot Open Interrupt Bit - Enable dot open interrupt
#define ISSI3733_ISR 0xF1 //Interrupt Status Register (Read Only)
#define ISSI3733_ISR_ABM3_FINISH 0x10 //Auto Breath Mode 3 Finish Bit - ABM3 finished
#define ISSI3733_ISR_ABM2_FINISH 0x08 //Auto Breath Mode 2 Finish Bit - ABM2 finished
#define ISSI3733_ISR_ABM1_FINISH 0x04 //Auto Breath Mode 1 Finish Bit - ABM1 finished
#define ISSI3733_ISR_SB 0x02 //Short Bit - Shorted
#define ISSI3733_ISR_OB 0x01 //Open Bit - Opened
#define ISSI3733_PG0 0x00 //LED Control Register
#define ISSI3733_PG1 0x01 //PWM Register
#define ISSI3733_PG2 0x02 //Auto Breath Mode Register
#define ISSI3733_PG3 0x03 //Function Register
#define ISSI3733_PG_ONOFF ISSI3733_PG0
#define ISSI3733_PG_OR ISSI3733_PG0
#define ISSI3733_PG_SR ISSI3733_PG0
#define ISSI3733_PG_PWM ISSI3733_PG1
#define ISSI3733_PG_ABM ISSI3733_PG2
#define ISSI3733_PG_FN ISSI3733_PG3
#define ISSI3733_CR 0x00 //Configuration Register
//PG3: Configuration Register: Synchronize Configuration
#define ISSI3733_CR_SYNC_MASTER 0x40 //Master
#define ISSI3733_CR_SYNC_SLAVE 0x80 //Slave
#define ISSI3733_CR_SYNC_HIGH_IMP 0xC0 //High Impedance
//PG3: Configuration Register: Open/Short Detection Enable Bit
//#define ISSI3733_CR_OSD_DISABLE 0x00 //Disable open/short detection
#define ISSI3733_CR_OSD_ENABLE 0x04 //Enable open/short detection
//PG3: Configuration Register: Auto Breath Enable
//#define ISSI3733_CR_B_EN_PWM 0x00 //PWM Mode Enable
#define ISSI3733_CR_B_EN_AUTO 0x02 //Auto Breath Mode Enable
//PG3: Configuration Register: Software Shutdown Control
//#define ISSI3733_CR_SSD_SHUTDOWN 0x00 //Software shutdown
#define ISSI3733_CR_SSD_NORMAL 0x01 //Normal operation
#define ISSI3733_GCCR 0x01 //Global Current Control Register
//1 Byte, Iout = (GCC / 256) * (840 / Rext)
//TODO: Give user define for Rext
//PG3: Auto Breath Control Register 1
#define ISSI3733_ABCR1_ABM1 0x02 //Auto Breath Control Register 1 of ABM-1
#define ISSI3733_ABCR1_ABM2 0x06 //Auto Breath Control Register 1 of ABM-2
#define ISSI3733_ABCR1_ABM3 0x0A //Auto Breath Control Register 1 of ABM-3
//Rise time
#define ISSI3733_ABCR1_T1_0021 0x00 //0.21s
#define ISSI3733_ABCR1_T1_0042 0x20 //0.42s
#define ISSI3733_ABCR1_T1_0084 0x40 //0.84s
#define ISSI3733_ABCR1_T1_0168 0x60 //1.68s
#define ISSI3733_ABCR1_T1_0336 0x80 //3.36s
#define ISSI3733_ABCR1_T1_0672 0xA0 //6.72s
#define ISSI3733_ABCR1_T1_1344 0xC0 //13.44s
#define ISSI3733_ABCR1_T1_2688 0xE0 //26.88s
//Max value time
#define ISSI3733_ABCR1_T2_0000 0x00 //0s
#define ISSI3733_ABCR1_T2_0021 0x02 //0.21s
#define ISSI3733_ABCR1_T2_0042 0x04 //0.42s
#define ISSI3733_ABCR1_T2_0084 0x06 //0.84s
#define ISSI3733_ABCR1_T2_0168 0x08 //1.68s
#define ISSI3733_ABCR1_T2_0336 0x0A //3.36s
#define ISSI3733_ABCR1_T2_0672 0x0C //6.72s
#define ISSI3733_ABCR1_T2_1344 0x0E //13.44s
#define ISSI3733_ABCR1_T2_2688 0x10 //26.88s
//PG3: Auto Breath Control Register 2
#define ISSI3733_ABCR2_ABM1 0x03 //Auto Breath Control Register 2 of ABM-1
#define ISSI3733_ABCR2_ABM2 0x07 //Auto Breath Control Register 2 of ABM-2
#define ISSI3733_ABCR2_ABM3 0x0B //Auto Breath Control Register 2 of ABM-3
//Fall time
#define ISSI3733_ABCR2_T3_0021 0x00 //0.21s
#define ISSI3733_ABCR2_T3_0042 0x20 //0.42s
#define ISSI3733_ABCR2_T3_0084 0x40 //0.84s
#define ISSI3733_ABCR2_T3_0168 0x60 //1.68s
#define ISSI3733_ABCR2_T3_0336 0x80 //3.36s
#define ISSI3733_ABCR2_T3_0672 0xA0 //6.72s
#define ISSI3733_ABCR2_T3_1344 0xC0 //13.44s
#define ISSI3733_ABCR2_T3_2688 0xE0 //26.88s
//Min value time
#define ISSI3733_ABCR2_T4_0000 0x00 //0s
#define ISSI3733_ABCR2_T4_0021 0x02 //0.21s
#define ISSI3733_ABCR2_T4_0042 0x04 //0.42s
#define ISSI3733_ABCR2_T4_0084 0x06 //0.84s
#define ISSI3733_ABCR2_T4_0168 0x08 //1.68s
#define ISSI3733_ABCR2_T4_0336 0x0A //3.36s
#define ISSI3733_ABCR2_T4_0672 0x0C //6.72s
#define ISSI3733_ABCR2_T4_1344 0x0E //13.44s
#define ISSI3733_ABCR2_T4_2688 0x10 //26.88s
#define ISSI3733_ABCR2_T4_5376 0x12 //53.76s
#define ISSI3733_ABCR2_T4_10752 0x14 //107.52s
//PG3: Auto Breath Control Register 3
#define ISSI3733_ABCR3_ABM1 0x04 //Auto Breath Control Register 3 of ABM-1
#define ISSI3733_ABCR3_ABM2 0x08 //Auto Breath Control Register 3 of ABM-2
#define ISSI3733_ABCR3_ABM3 0x0C //Auto Breath Control Register 3 of ABM-3
#define ISSI3733_ABCR3_LTA_LOOP_ENDLESS 0x00
#define ISSI3733_ABCR3_LTA_LOOP_1 0x01
#define ISSI3733_ABCR3_LTA_LOOP_2 0x02
#define ISSI3733_ABCR3_LTA_LOOP_3 0x03
#define ISSI3733_ABCR3_LTA_LOOP_4 0x04
#define ISSI3733_ABCR3_LTA_LOOP_5 0x05
#define ISSI3733_ABCR3_LTA_LOOP_6 0x06
#define ISSI3733_ABCR3_LTA_LOOP_7 0x07
#define ISSI3733_ABCR3_LTA_LOOP_8 0x08
#define ISSI3733_ABCR3_LTA_LOOP_9 0x09
#define ISSI3733_ABCR3_LTA_LOOP_10 0x0A
#define ISSI3733_ABCR3_LTA_LOOP_11 0x0B
#define ISSI3733_ABCR3_LTA_LOOP_12 0x0C
#define ISSI3733_ABCR3_LTA_LOOP_13 0x0D
#define ISSI3733_ABCR3_LTA_LOOP_14 0x0E
#define ISSI3733_ABCR3_LTA_LOOP_15 0x0F
//Loop Begin
#define ISSI3733_ABCR3_LB_T1 0x00
#define ISSI3733_ABCR3_LB_T2 0x10
#define ISSI3733_ABCR3_LB_T3 0x20
#define ISSI3733_ABCR3_LB_T4 0x30
//Loop End
#define ISSI3733_ABCR3_LE_T3 0x00 //End at Off state
#define ISSI3733_ABCR3_LE_T1 0x40 //End at On State
//PG3: Auto Breath Control Register 4
#define ISSI3733_ABCR4_ABM1 0x05 //Auto Breath Control Register 4 of ABM-1
#define ISSI3733_ABCR4_ABM2 0x09 //Auto Breath Control Register 4 of ABM-2
#define ISSI3733_ABCR4_ABM3 0x0D //Auto Breath Control Register 4 of ABM-3
#define ISSI3733_ABCR4_LTB_LOOP_ENDLESS 0x00
//Or 8bit loop times
//PG3: Time Update Register
#define ISSI3733_TUR 0x0E
#define ISSI3733_TUR_UPDATE 0x00 //Write to update 02h~0Dh time registers after configuring
//PG3: SWy Pull-Up Resistor Selection Register
#define ISSI3733_SWYR_PUR 0x0F
#define ISSI3733_SWYR_PUR_NONE 0x00 //No pull-up resistor
#define ISSI3733_SWYR_PUR_500 0x01 //0.5k Ohm
#define ISSI3733_SWYR_PUR_1000 0x02 //1.0k Ohm
#define ISSI3733_SWYR_PUR_2000 0x03 //2.0k Ohm
#define ISSI3733_SWYR_PUR_4000 0x04 //4.0k Ohm
#define ISSI3733_SWYR_PUR_8000 0x05 //8.0k Ohm
#define ISSI3733_SWYR_PUR_16000 0x06 //16k Ohm
#define ISSI3733_SWYR_PUR_32000 0x07 //32k Ohm
//PG3: CSx Pull-Down Resistor Selection Register
#define ISSI3733_CSXR_PDR 0x10
#define ISSI3733_CSXR_PDR_NONE 0x00 //No pull-down resistor
#define ISSI3733_CSXR_PDR_500 0x01 //0.5k Ohm
#define ISSI3733_CSXR_PDR_1000 0x02 //1.0k Ohm
#define ISSI3733_CSXR_PDR_2000 0x03 //2.0k Ohm
#define ISSI3733_CSXR_PDR_4000 0x04 //4.0k Ohm
#define ISSI3733_CSXR_PDR_8000 0x05 //8.0k Ohm
#define ISSI3733_CSXR_PDR_16000 0x06 //16k Ohm
#define ISSI3733_CSXR_PDR_32000 0x07 //32k Ohm
//PG3: Reset Register
#define ISSI3733_RR 0x11 //Read to reset all registers to default values
#endif //_ISSI3733_DRIVER_H_

View File

@ -0,0 +1,509 @@
/*
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/>.
*/
#include "arm_atsam_protocol.h"
#include "tmk_core/common/led.h"
#include <string.h>
void SERCOM1_0_Handler( void )
{
if (SERCOM1->I2CM.INTFLAG.bit.ERROR)
{
SERCOM1->I2CM.INTFLAG.reg = SERCOM_I2CM_INTENCLR_ERROR;
}
}
void DMAC_0_Handler( void )
{
if (DMAC->Channel[0].CHINTFLAG.bit.TCMPL)
{
DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
i2c1_stop();
i2c_led_q_running = 0;
i2c_led_q_run();
return;
}
if (DMAC->Channel[0].CHINTFLAG.bit.TERR)
{
DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
}
}
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
uint8_t gcr_desired;
uint8_t gcr_breathe;
uint8_t gcr_use;
uint8_t gcr_actual;
uint8_t gcr_actual_last;
#define ACT_GCR_NONE 0
#define ACT_GCR_INC 1
#define ACT_GCR_DEC 2
#define LED_GCR_STEP_AUTO 2
static uint8_t gcr_min_counter;
static uint8_t v_5v_cat_hit;
//WARNING: Automatic GCR is in place to prevent USB shutdown and LED driver overloading
void gcr_compute(void)
{
uint8_t action = ACT_GCR_NONE;
if (led_animation_breathing)
gcr_use = gcr_breathe;
else
gcr_use = gcr_desired;
//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)
{
I2C3733_Control_Set(0);
//CDC_print("USB: WARNING: 5V catastrophic level reached! Disabling LED drivers!\r\n"); //Blocking print is bad here!
v_5v_cat_hit = 20; //~100ms recover
gcr_actual = 0; //Minimize GCR
usb_gcr_auto = 1; //Force auto mode enabled
return;
}
else if (v_5v_cat_hit > 1)
{
v_5v_cat_hit--;
return;
}
else if (v_5v_cat_hit == 1)
{
I2C3733_Control_Set(1);
CDC_print("USB: WARNING: Re-enabling LED drivers\r\n");
v_5v_cat_hit = 0;
return;
}
if (usb_gcr_auto)
{
if (v_5v_avg < V5_LOW) action = ACT_GCR_DEC;
else if (v_5v_avg > V5_HIGH && gcr_actual < gcr_use) action = ACT_GCR_INC;
else if (gcr_actual > gcr_use) action = ACT_GCR_DEC;
}
else
{
if (gcr_actual < gcr_use) action = ACT_GCR_INC;
else if (gcr_actual > gcr_use) action = ACT_GCR_DEC;
}
if (action == ACT_GCR_NONE)
{
gcr_min_counter = 0;
}
else if (action == ACT_GCR_INC)
{
if (LED_GCR_STEP_AUTO > LED_GCR_MAX - gcr_actual) gcr_actual = LED_GCR_MAX; //Obey max and prevent wrapping
else gcr_actual += LED_GCR_STEP_AUTO;
gcr_min_counter = 0;
}
else if (action == ACT_GCR_DEC)
{
if (LED_GCR_STEP_AUTO > gcr_actual) //Prevent wrapping
{
gcr_actual = 0;
//At this point, power can no longer be cut from the LED drivers, so focus on cutting out extra port if active
if (usb_extra_state != USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) //If not in a wait for replug state
{
if (usb_extra_state == USB_EXTRA_STATE_ENABLED) //If extra usb is enabled
{
gcr_min_counter++;
if (gcr_min_counter > 200) //5ms per check = 1s delay
{
USB_ExtraSetState(USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG);
usb_extra_manual = 0; //Force disable manual mode of extra port
if (usb_extra_manual) CDC_print("USB: Disabling extra port until replug and manual mode toggle!\r\n");
else CDC_print("USB: Disabling extra port until replug!\r\n");
}
}
}
}
else
{
//Power successfully cut back from LED drivers
gcr_actual -= LED_GCR_STEP_AUTO;
gcr_min_counter = 0;
//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)
{
gcr_breathe = gcr_actual;
//PS: At this point, setting breathing to exhale makes a noticebly shorter cycle
// and the same would happen maybe one or two more times. Therefore I'm favoring
// powering through one full breathe and letting gcr settle completely
}
}
}
}
led_disp_t disp;
void issi3733_prepare_arrays(void)
{
memset(issidrv,0,sizeof(issi3733_driver_t) * ISSI3733_DRIVER_COUNT);
int i;
uint8_t addrs[ISSI3733_DRIVER_COUNT] = ISSI3773_DRIVER_ADDRESSES;
for (i=0;i<ISSI3733_DRIVER_COUNT;i++)
{
issidrv[i].addr = addrs[i];
}
issi3733_led_t *cur = led_map;
while (cur < lede)
{
//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));
//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.top) / disp.height * 100;
*cur->rgb.r = 0;
*cur->rgb.g = 0;
*cur->rgb.b = 0;
cur++;
}
}
void led_matrix_prepare(void)
{
disp_calc_extents();
disp_pixel_setup();
}
uint8_t led_enabled;
float led_animation_speed;
uint8_t led_animation_direction;
uint8_t led_animation_breathing;
uint8_t led_animation_breathe_cur;
uint8_t breathe_step;
uint8_t breathe_dir;
uint64_t led_next_run;
uint8_t led_animation_id;
uint8_t led_lighting_mode;
issi3733_led_t *led_cur;
uint8_t led_per_run = 15;
float breathe_mult;
void led_matrix_run(led_setup_t *f)
{
float ro;
float go;
float bo;
float px;
uint8_t led_this_run = 0;
if (led_cur == 0) //Denotes start of new processing cycle in the case of chunked processing
{
led_cur = led_map;
disp.frame += 1;
breathe_mult = 1;
if (led_animation_breathing)
{
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;
}
}
uint8_t fcur = 0;
uint8_t fmax = 0;
//Frames setup
while (f[fcur].end != 1)
{
fcur++; //Count frames
}
fmax = fcur; //Store total frames count
while (led_cur < lede && led_this_run < led_per_run)
{
ro = 0;
go = 0;
bo = 0;
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
{
//Act on LED
for (fcur = 0; fcur < fmax; fcur++)
{
px = led_cur->px;
float pxmod;
pxmod = (float)(disp.frame % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
//Add in any moving effects
if ((!led_animation_direction && f[fcur].ef & EF_SCR_R) || (led_animation_direction && (f[fcur].ef & EF_SCR_L)))
{
pxmod *= 100.0f;
pxmod = (uint32_t)pxmod % 10000;
pxmod /= 100.0f;
px -= pxmod;
if (px > 100) px -= 100;
else if (px < 0) px += 100;
}
else if ((!led_animation_direction && f[fcur].ef & EF_SCR_L) || (led_animation_direction && (f[fcur].ef & EF_SCR_R)))
{
pxmod *= 100.0f;
pxmod = (uint32_t)pxmod % 10000;
pxmod /= 100.0f;
px += pxmod;
if (px > 100) px -= 100;
else if (px < 0) px += 100;
}
//Check if LED's px is in current frame
if (px < f[fcur].hs) continue;
if (px > f[fcur].he) continue;
//note: < 0 or > 100 continue
//Calculate the px within the start-stop percentage for color blending
px = (px - f[fcur].hs) / (f[fcur].he - f[fcur].hs);
//Add in any color effects
if (f[fcur].ef & EF_OVER)
{
ro = (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
go = (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
bo = (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
}
else if (f[fcur].ef & EF_SUBTRACT)
{
ro -= (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
go -= (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
bo -= (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
}
else
{
ro += (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
go += (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
bo += (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
}
}
}
//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;
if (led_animation_breathing)
{
ro *= breathe_mult;
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_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;
led_matrix_run((led_setup_t*)led_setups[led_animation_id]);
DBGC(DC_LED_MATRIX_INIT_COMPLETE);
return 0;
}
#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((led_setup_t*)led_setups[led_animation_id]);
//m15_on; //debug profiling
}
}

View File

@ -0,0 +1,142 @@
/*
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/>.
*/
#ifndef _LED_MATRIX_H_
#define _LED_MATRIX_H_
//From keyboard
#include "config_led.h"
//CS1-CS16 Current Source "Col"
#define ISSI3733_CS_COUNT 16
//SW1-SW12 Switch "Row"
#define ISSI3733_SW_COUNT 12
#define ISSI3733_LED_RGB_COUNT ISSI3733_CS_COUNT * ISSI3733_SW_COUNT
#define ISSI3733_PG0_BYTES ISSI3733_LED_RGB_COUNT / 8 + 1 //+1 for first byte being memory start offset for I2C transfer
#define ISSI3733_PG1_BYTES ISSI3733_LED_RGB_COUNT + 1 //+1 for first byte being memory start offset for I2C transfer
#define ISSI3733_PG2_BYTES ISSI3733_LED_RGB_COUNT + 1 //+1 for first byte being memory start offset for I2C transfer
#define ISSI3733_PG3_BYTES 18 + 1 //+1 for first byte being memory start offset for I2C transfer
#define ISSI3733_PG_ONOFF_BYTES ISSI3733_PG0_BYTES
#define ISSI3733_PG_OR_BYTES ISSI3733_PG0_BYTES
#define ISSI3733_PG_SR_BYTES ISSI3733_PG0_BYTES
#define ISSI3733_PG_PWM_BYTES ISSI3733_PG1_BYTES
#define ISSI3733_PG_ABM_BYTES ISSI3733_PG2_BYTES
#define ISSI3733_PG_FN_BYTES ISSI3733_PG3_BYTES
typedef struct issi3733_driver_s {
uint8_t addr; //Address of the driver according to wiring "ISSI3733: Table 1 Slave Address"
uint8_t onoff[ISSI3733_PG_ONOFF_BYTES]; //PG0 - LED Control Register - LED On/Off Register
uint8_t open[ISSI3733_PG_OR_BYTES]; //PG0 - LED Control Register - LED Open Register
uint8_t shrt[ISSI3733_PG_SR_BYTES]; //PG0 - LED Control Register - LED Short Register
uint8_t pwm[ISSI3733_PG_PWM_BYTES]; //PG1 - PWM Register
uint8_t abm[ISSI3733_PG_ABM_BYTES]; //PG2 - Auto Breath Mode Register
uint8_t conf[ISSI3733_PG_FN_BYTES]; //PG3 - Function Register
} issi3733_driver_t;
typedef struct issi3733_rgb_s {
uint8_t *r; //Direct access into PWM data
uint8_t *g; //Direct access into PWM data
uint8_t *b; //Direct access into PWM data
} issi3733_rgb_t;
typedef struct issi3733_rgb_adr_s {
uint8_t drv; //Driver from given list
uint8_t cs; //CS
uint8_t swr; //SW Red
uint8_t swg; //SW Green
uint8_t swb; //SW Blue
} issi3733_rgb_adr_t;
typedef struct issi3733_led_s {
uint8_t id; //According to PCB ref
issi3733_rgb_t rgb; //PWM settings of R G B
issi3733_rgb_adr_t adr; //Hardware addresses
float x; //Physical position X
float y; //Physical position Y
float px; //Physical position X in percent
float py; //Physical position Y in percent
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;
uint8_t led_matrix_init(void);
#define LED_MODE_NORMAL 0 //Must be 0
#define LED_MODE_KEYS_ONLY 1
#define LED_MODE_NON_KEYS_ONLY 2
#define LED_MODE_INDICATORS_ONLY 3
#define LED_MODE_MAX_INDEX LED_MODE_INDICATORS_ONLY //Must be highest value
#define EF_NONE 0x00000000 //No effect
#define EF_OVER 0x00000001 //Overwrite any previous color information with new
#define EF_SCR_L 0x00000002 //Scroll left
#define EF_SCR_R 0x00000004 //Scroll right
#define EF_SUBTRACT 0x00000008 //Subtract color values
typedef struct led_setup_s {
float hs; //Band begin at percent
float he; //Band end at percent
uint8_t rs; //Red start value
uint8_t re; //Red end value
uint8_t gs; //Green start value
uint8_t ge; //Green end value
uint8_t bs; //Blue start value
uint8_t be; //Blue end value
uint32_t ef; //Animation and color effects
uint8_t end; //Set to signal end of the setup
} led_setup_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_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 issi3733_led_t *led_cur;
extern issi3733_led_t *lede;
void led_matrix_run(led_setup_t *f);
void led_matrix_task(void);
void gcr_compute(void);
#endif //_LED_MATRIX_H_

View File

@ -0,0 +1,279 @@
/*
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/>.
*/
#include "samd51j18a.h"
#include "tmk_core/common/keyboard.h"
#include "report.h"
#include "host.h"
#include "host_driver.h"
#include "keycode_config.h"
#include <string.h>
#include "quantum.h"
//From protocol directory
#include "arm_atsam_protocol.h"
//From keyboard's directory
#include "config_led.h"
uint8_t keyboard_leds(void);
void send_keyboard(report_keyboard_t *report);
void send_mouse(report_mouse_t *report);
void send_system(uint16_t data);
void send_consumer(uint16_t data);
host_driver_t arm_atsam_driver = {
keyboard_leds,
send_keyboard,
send_mouse,
send_system,
send_consumer
};
uint8_t led_states;
uint8_t keyboard_leds(void)
{
#ifdef NKRO_ENABLE
if (keymap_config.nkro)
return udi_hid_nkro_report_set;
else
#endif //NKRO_ENABLE
return udi_hid_kbd_report_set;
}
void send_keyboard(report_keyboard_t *report)
{
uint32_t irqflags;
#ifdef NKRO_ENABLE
if (!keymap_config.nkro)
{
#endif //NKRO_ENABLE
dprint("s-kbd\r\n");
irqflags = __get_PRIMASK();
__disable_irq();
__DMB();
memcpy(udi_hid_kbd_report, report->raw, UDI_HID_KBD_REPORT_SIZE);
udi_hid_kbd_b_report_valid = 1;
udi_hid_kbd_send_report();
__DMB();
__set_PRIMASK(irqflags);
#ifdef NKRO_ENABLE
}
else
{
dprint("s-nkro\r\n");
irqflags = __get_PRIMASK();
__disable_irq();
__DMB();
memcpy(udi_hid_nkro_report, report->raw, UDI_HID_NKRO_REPORT_SIZE);
udi_hid_nkro_b_report_valid = 1;
udi_hid_nkro_send_report();
__DMB();
__set_PRIMASK(irqflags);
}
#endif //NKRO_ENABLE
}
void send_mouse(report_mouse_t *report)
{
#ifdef MOUSEKEY_ENABLE
uint32_t irqflags;
dprint("s-mou\r\n");
irqflags = __get_PRIMASK();
__disable_irq();
__DMB();
memcpy(udi_hid_mou_report, report, UDI_HID_MOU_REPORT_SIZE);
udi_hid_mou_b_report_valid = 1;
udi_hid_mou_send_report();
__DMB();
__set_PRIMASK(irqflags);
#endif //MOUSEKEY_ENABLE
}
void send_system(uint16_t data)
{
#ifdef EXTRAKEY_ENABLE
dprintf("s-exks %i\r\n", data);
uint32_t irqflags;
irqflags = __get_PRIMASK();
__disable_irq();
__DMB();
udi_hid_exk_report.desc.report_id = REPORT_ID_SYSTEM;
if (data != 0) data = data - SYSTEM_POWER_DOWN + 1;
udi_hid_exk_report.desc.report_data = data;
udi_hid_exk_b_report_valid = 1;
udi_hid_exk_send_report();
__DMB();
__set_PRIMASK(irqflags);
#endif //EXTRAKEY_ENABLE
}
void send_consumer(uint16_t data)
{
#ifdef EXTRAKEY_ENABLE
dprintf("s-exkc %i\r\n",data);
uint32_t irqflags;
irqflags = __get_PRIMASK();
__disable_irq();
__DMB();
udi_hid_exk_report.desc.report_id = REPORT_ID_CONSUMER;
udi_hid_exk_report.desc.report_data = data;
udi_hid_exk_b_report_valid = 1;
udi_hid_exk_send_report();
__DMB();
__set_PRIMASK(irqflags);
#endif //EXTRAKEY_ENABLE
}
int main(void)
{
led_ena;
m15_ena;
debug_code_init();
CLK_init();
ADC0_init();
SPI_Init();
i2c1_init();
matrix_init();
USB2422_init();
DBGC(DC_MAIN_UDC_START_BEGIN);
udc_start();
DBGC(DC_MAIN_UDC_START_COMPLETE);
DBGC(DC_MAIN_CDC_INIT_BEGIN);
CDC_init();
DBGC(DC_MAIN_CDC_INIT_COMPLETE);
while (USB2422_Port_Detect_Init() == 0) {}
led_off;
m15_off;
led_matrix_init();
while (I2C3733_Init_Control() != 1) {}
while (I2C3733_Init_Drivers() != 1) {}
I2C_DMAC_LED_Init();
i2c_led_q_init();
uint8_t drvid;
for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
I2C_LED_Q_ONOFF(drvid); //Queue data
keyboard_setup();
keyboard_init();
host_set_driver(&arm_atsam_driver);
#ifdef VIRTSER_ENABLE
uint64_t next_print = 0;
#endif //VIRTSER_ENABLE
uint64_t next_usb_checkup = 0;
uint64_t next_5v_checkup = 0;
v_5v_avg = adc_get(ADC_5V);
debug_code_disable();
while (1)
{
if (usb_state == USB_STATE_POWERDOWN)
{
led_on;
if (led_enabled)
{
for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
{
I2C3733_Control_Set(0);
}
}
while (usb_state == USB_STATE_POWERDOWN) {}
if (led_enabled)
{
for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
{
I2C3733_Control_Set(1);
}
}
led_off;
}
keyboard_task();
led_matrix_task();
if (CLK_get_ms() > next_5v_checkup)
{
next_5v_checkup = CLK_get_ms() + 5;
v_5v = adc_get(ADC_5V);
v_5v_avg = 0.9 * v_5v_avg + 0.1 * v_5v;
gcr_compute();
}
if (CLK_get_ms() > next_usb_checkup)
{
next_usb_checkup = CLK_get_ms() + 10;
USB_HandleExtraDevice();
}
#ifdef VIRTSER_ENABLE
if (CLK_get_ms() > next_print)
{
next_print = CLK_get_ms() + 250;
//dpf("5v=%i 5vu=%i dlow=%i dhi=%i gca=%i gcd=%i\r\n",v_5v,v_5v_avg,v_5v_avg-V5_LOW,v_5v_avg-V5_HIGH,gcr_actual,gcr_desired);
}
#endif //VIRTSER_ENABLE
}
return 1;
}

View File

@ -0,0 +1,23 @@
/*
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/>.
*/
#ifndef _MAIN_ARM_ATSAM_H_
#define _MAIN_ARM_ATSAM_H_
uint8_t keyboard_leds(void);
#endif //_MAIN_ARM_ATSAM_H_

View File

@ -0,0 +1,18 @@
#ifndef _MD_BOOTLOADER_H_
#define _MD_BOOTLOADER_H_
extern uint32_t _srom;
extern uint32_t _lrom;
extern uint32_t _erom;
#define BOOTLOADER_SERIAL_MAX_SIZE 20 //DO NOT MODIFY!
#ifdef MD_BOOTLOADER
#define MCU_HZ 48000000
#define I2C_HZ 0 //Not used
#endif //MD_BOOTLOADER
#endif //_MD_BOOTLOADER_H_

View File

@ -0,0 +1,90 @@
/*
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/>.
*/
#include "arm_atsam_protocol.h"
Srdata_t srdata;
void SPI_WriteSRData(void)
{
uint16_t timeout;
SC2_RCLCK_LO;
timeout = 50000;
while (!(SCSPI->SPI.INTFLAG.bit.DRE) && --timeout) { DBGC(DC_SPI_WRITE_DRE); }
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); }
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;
}
void SPI_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;
//Configure Shift Registers
SC2_DIRSET;
SC2_RCLCK_HI;
SC2_OE_DIS;
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
SCSPI->SPI.CTRLA.bit.ENABLE = 1;
timeout = 50000;
while (SCSPI->SPI.SYNCBUSY.bit.ENABLE && timeout--) { 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();
//Enable register output
SC2_OE_ENA;
DBGC(DC_SPI_INIT_COMPLETE);
}

View File

@ -0,0 +1,63 @@
/*
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/>.
*/
#ifndef _SPI_H_
#define _SPI_H_
//TODO: PS: Should bring ports to keyboard configuration
#define SCSPI SERCOM2
#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 */
typedef union {
struct {
uint16_t RSVD4:1; /*!< bit: 0 */
uint16_t RSVD3:1; /*!< bit: 1 */
uint16_t RSVD2:1; /*!< bit: 2 */
uint16_t RSVD1:1; /*!< bit: 3 */
uint16_t SDB_N:1; /*!< bit: 4 SHUTDOWN THE CHIP WHEN 0, RUN WHEN 1 */
uint16_t IRST:1; /*!< bit: 5 RESET THE IS3733 I2C WHEN 1, RUN WHEN 0 */
uint16_t SRC_2:1; /*!< bit: 6 ADVERTISE A SOURCE TO USBC-2 CC */
uint16_t SRC_1:1; /*!< bit: 7 ADVERTISE A SOURCE TO USBC-1 CC */
uint16_t E_VBUS_2:1; /*!< bit: 8 ENABLE 5V OUT TO USBC-2 WHEN 1 */
uint16_t E_VBUS_1:1; /*!< bit: 9 ENABLE 5V OUT TO USBC-1 WHEN 1 */
uint16_t E_DN1_N:1; /*!< bit: 10 ENABLE DN1 1:2 MUX WHEN 0 */
uint16_t S_DN1:1; /*!< bit: 11 SELECT DN1 PATH 0:USBC-1, 1:USBC-2 */
uint16_t E_UP_N:1; /*!< bit: 12 ENABLE SUP 1:2 MUX WHEN 0 */
uint16_t S_UP:1; /*!< bit: 13 SELECT UP PATH 0:USBC-1, 1:USBC-2 */
uint16_t HUB_RESET_N:1; /*!< bit: 14 RESET USB HUB WHEN 0, RUN WHEN 1 */
uint16_t HUB_CONNECT:1; /*!< bit: 15 SIGNAL VBUS CONNECT TO USB HUB WHEN 1 */
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} Srdata_t;
extern Srdata_t srdata;
void SPI_WriteSRData(void);
void SPI_Init(void);
#endif //_SPI_H_

View File

@ -0,0 +1,548 @@
/**
* \file
*
* \brief gcc starttup file for SAMD51
*
* Copyright (c) 2017 Microchip Technology Inc.
*
* \asf_license_start
*
* \page License
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the Licence at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \asf_license_stop
*
*/
#include "samd51.h"
/* Initialize segments */
extern uint32_t _sfixed;
extern uint32_t _efixed;
extern uint32_t _etext;
extern uint32_t _srelocate;
extern uint32_t _erelocate;
extern uint32_t _szero;
extern uint32_t _ezero;
extern uint32_t _sstack;
extern uint32_t _estack;
/** \cond DOXYGEN_SHOULD_SKIP_THIS */
int main(void);
/** \endcond */
void __libc_init_array(void);
/* Default empty handler */
void Dummy_Handler(void);
/* Cortex-M4 core handlers */
void NMI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MemManage_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void BusFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UsageFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SVC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DebugMon_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PendSV_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SysTick_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
/* Peripherals handlers */
void PM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCLK_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void OSCCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 */
void OSCCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 */
void OSCCTRL_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY */
void OSCCTRL_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */
void OSCCTRL_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 */
void OSC32KCTRL_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SUPC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SUPC_B12SRDY, SUPC_B33SRDY, SUPC_BOD12RDY, SUPC_BOD33RDY, SUPC_VCORERDY, SUPC_VREGRDY */
void SUPC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SUPC_BOD12DET, SUPC_BOD33DET */
void WDT_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RTC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_0 */
void EIC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_1 */
void EIC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_2 */
void EIC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_3 */
void EIC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_4 */
void EIC_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_5 */
void EIC_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_6 */
void EIC_7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_7 */
void EIC_8_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_8 */
void EIC_9_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_9 */
void EIC_10_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_10 */
void EIC_11_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_11 */
void EIC_12_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_12 */
void EIC_13_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_13 */
void EIC_14_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_14 */
void EIC_15_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_15 */
void FREQM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void NVMCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* NVMCTRL_0, NVMCTRL_1, NVMCTRL_2, NVMCTRL_3, NVMCTRL_4, NVMCTRL_5, NVMCTRL_6, NVMCTRL_7 */
void NVMCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* NVMCTRL_10, NVMCTRL_8, NVMCTRL_9 */
void DMAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 */
void DMAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 */
void DMAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 */
void DMAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 */
void DMAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_10, DMAC_SUSP_11, DMAC_SUSP_12, DMAC_SUSP_13, DMAC_SUSP_14, DMAC_SUSP_15, DMAC_SUSP_16, DMAC_SUSP_17, DMAC_SUSP_18, DMAC_SUSP_19, DMAC_SUSP_20, DMAC_SUSP_21, DMAC_SUSP_22, DMAC_SUSP_23, DMAC_SUSP_24, DMAC_SUSP_25, DMAC_SUSP_26, DMAC_SUSP_27, DMAC_SUSP_28, DMAC_SUSP_29, DMAC_SUSP_30, DMAC_SUSP_31, DMAC_SUSP_4, DMAC_SUSP_5, DMAC_SUSP_6, DMAC_SUSP_7, DMAC_SUSP_8, DMAC_SUSP_9, DMAC_TCMPL_10, DMAC_TCMPL_11, DMAC_TCMPL_12, DMAC_TCMPL_13, DMAC_TCMPL_14, DMAC_TCMPL_15, DMAC_TCMPL_16, DMAC_TCMPL_17, DMAC_TCMPL_18, DMAC_TCMPL_19, DMAC_TCMPL_20, DMAC_TCMPL_21, DMAC_TCMPL_22, DMAC_TCMPL_23, DMAC_TCMPL_24, DMAC_TCMPL_25, DMAC_TCMPL_26, DMAC_TCMPL_27, DMAC_TCMPL_28, DMAC_TCMPL_29, DMAC_TCMPL_30, DMAC_TCMPL_31, DMAC_TCMPL_4, DMAC_TCMPL_5, DMAC_TCMPL_6, DMAC_TCMPL_7, DMAC_TCMPL_8, DMAC_TCMPL_9, DMAC_TERR_10, DMAC_TERR_11, DMAC_TERR_12, DMAC_TERR_13, DMAC_TERR_14, DMAC_TERR_15, DMAC_TERR_16, DMAC_TERR_17, DMAC_TERR_18, DMAC_TERR_19, DMAC_TERR_20, DMAC_TERR_21, DMAC_TERR_22, DMAC_TERR_23, DMAC_TERR_24, DMAC_TERR_25, DMAC_TERR_26, DMAC_TERR_27, DMAC_TERR_28, DMAC_TERR_29, DMAC_TERR_30, DMAC_TERR_31, DMAC_TERR_4, DMAC_TERR_5, DMAC_TERR_6, DMAC_TERR_7, DMAC_TERR_8, DMAC_TERR_9 */
void EVSYS_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_0, EVSYS_OVR_0 */
void EVSYS_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_1, EVSYS_OVR_1 */
void EVSYS_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_2, EVSYS_OVR_2 */
void EVSYS_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_3, EVSYS_OVR_3 */
void EVSYS_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_10, EVSYS_EVD_11, EVSYS_EVD_4, EVSYS_EVD_5, EVSYS_EVD_6, EVSYS_EVD_7, EVSYS_EVD_8, EVSYS_EVD_9, EVSYS_OVR_10, EVSYS_OVR_11, EVSYS_OVR_4, EVSYS_OVR_5, EVSYS_OVR_6, EVSYS_OVR_7, EVSYS_OVR_8, EVSYS_OVR_9 */
void PAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TAL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TAL_BRK */
void TAL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TAL_IPS_0, TAL_IPS_1 */
void RAMECC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_0 */
void SERCOM0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_1 */
void SERCOM0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_2 */
void SERCOM0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_3, SERCOM0_4, SERCOM0_5, SERCOM0_6 */
void SERCOM1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_0 */
void SERCOM1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_1 */
void SERCOM1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_2 */
void SERCOM1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_3, SERCOM1_4, SERCOM1_5, SERCOM1_6 */
void SERCOM2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_0 */
void SERCOM2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_1 */
void SERCOM2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_2 */
void SERCOM2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_3, SERCOM2_4, SERCOM2_5, SERCOM2_6 */
void SERCOM3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_0 */
void SERCOM3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_1 */
void SERCOM3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_2 */
void SERCOM3_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_3, SERCOM3_4, SERCOM3_5, SERCOM3_6 */
#ifdef ID_SERCOM4
void SERCOM4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_0 */
void SERCOM4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_1 */
void SERCOM4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_2 */
void SERCOM4_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_3, SERCOM4_4, SERCOM4_5, SERCOM4_6 */
#endif
#ifdef ID_SERCOM5
void SERCOM5_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_0 */
void SERCOM5_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_1 */
void SERCOM5_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_2 */
void SERCOM5_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_3, SERCOM5_4, SERCOM5_5, SERCOM5_6 */
#endif
#ifdef ID_SERCOM6
void SERCOM6_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_0 */
void SERCOM6_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_1 */
void SERCOM6_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_2 */
void SERCOM6_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_3, SERCOM6_4, SERCOM6_5, SERCOM6_6 */
#endif
#ifdef ID_SERCOM7
void SERCOM7_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_0 */
void SERCOM7_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_1 */
void SERCOM7_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_2 */
void SERCOM7_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_3, SERCOM7_4, SERCOM7_5, SERCOM7_6 */
#endif
#ifdef ID_CAN0
void CAN0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_CAN1
void CAN1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_USB
void USB_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
void USB_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_SOF_HSOF */
void USB_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */
void USB_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */
#endif
#ifdef ID_GMAC
void GMAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
void TCC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_CNT_A, TCC0_DFS_A, TCC0_ERR_A, TCC0_FAULT0_A, TCC0_FAULT1_A, TCC0_FAULTA_A, TCC0_FAULTB_A, TCC0_OVF, TCC0_TRG, TCC0_UFS_A */
void TCC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_0 */
void TCC0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_1 */
void TCC0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_2 */
void TCC0_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_3 */
void TCC0_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_4 */
void TCC0_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_5 */
void TCC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_CNT_A, TCC1_DFS_A, TCC1_ERR_A, TCC1_FAULT0_A, TCC1_FAULT1_A, TCC1_FAULTA_A, TCC1_FAULTB_A, TCC1_OVF, TCC1_TRG, TCC1_UFS_A */
void TCC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_0 */
void TCC1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_1 */
void TCC1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_2 */
void TCC1_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_3 */
void TCC2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_CNT_A, TCC2_DFS_A, TCC2_ERR_A, TCC2_FAULT0_A, TCC2_FAULT1_A, TCC2_FAULTA_A, TCC2_FAULTB_A, TCC2_OVF, TCC2_TRG, TCC2_UFS_A */
void TCC2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_0 */
void TCC2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_1 */
void TCC2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_2 */
#ifdef ID_TCC3
void TCC3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_CNT_A, TCC3_DFS_A, TCC3_ERR_A, TCC3_FAULT0_A, TCC3_FAULT1_A, TCC3_FAULTA_A, TCC3_FAULTB_A, TCC3_OVF, TCC3_TRG, TCC3_UFS_A */
void TCC3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_MC_0 */
void TCC3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_MC_1 */
#endif
#ifdef ID_TCC4
void TCC4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_CNT_A, TCC4_DFS_A, TCC4_ERR_A, TCC4_FAULT0_A, TCC4_FAULT1_A, TCC4_FAULTA_A, TCC4_FAULTB_A, TCC4_OVF, TCC4_TRG, TCC4_UFS_A */
void TCC4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_MC_0 */
void TCC4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_MC_1 */
#endif
void TC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#ifdef ID_TC4
void TC4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_TC5
void TC5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_TC6
void TC6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_TC7
void TC7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
void PDEC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A */
void PDEC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_MC_0 */
void PDEC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_MC_1 */
void ADC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC0_OVERRUN, ADC0_WINMON */
void ADC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC0_RESRDY */
void ADC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC1_OVERRUN, ADC1_WINMON */
void ADC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC1_RESRDY */
void AC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_OVERRUN_A_0, DAC_OVERRUN_A_1, DAC_UNDERRUN_A_0, DAC_UNDERRUN_A_1 */
void DAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_EMPTY_0 */
void DAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_EMPTY_1 */
void DAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_RESRDY_0 */
void DAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_RESRDY_1 */
#ifdef ID_I2S
void I2S_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
void PCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AES_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TRNG_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#ifdef ID_ICM
void ICM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_PUKCC
void PUKCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
void QSPI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#ifdef ID_SDHC0
void SDHC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_SDHC1
void SDHC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
/* Exception Table */
__attribute__ ((section(".vectors")))
const DeviceVectors exception_table = {
/* Configure Initial Stack Pointer, using linker-generated symbols */
.pvStack = (void*) (&_estack),
.pfnReset_Handler = (void*) Reset_Handler,
.pfnNMI_Handler = (void*) NMI_Handler,
.pfnHardFault_Handler = (void*) HardFault_Handler,
.pfnMemManage_Handler = (void*) MemManage_Handler,
.pfnBusFault_Handler = (void*) BusFault_Handler,
.pfnUsageFault_Handler = (void*) UsageFault_Handler,
.pvReservedM9 = (void*) (0UL), /* Reserved */
.pvReservedM8 = (void*) (0UL), /* Reserved */
.pvReservedM7 = (void*) (0UL), /* Reserved */
.pvReservedM6 = (void*) (0UL), /* Reserved */
.pfnSVC_Handler = (void*) SVC_Handler,
.pfnDebugMon_Handler = (void*) DebugMon_Handler,
.pvReservedM3 = (void*) (0UL), /* Reserved */
.pfnPendSV_Handler = (void*) PendSV_Handler,
.pfnSysTick_Handler = (void*) SysTick_Handler,
/* Configurable interrupts */
.pfnPM_Handler = (void*) PM_Handler, /* 0 Power Manager */
.pfnMCLK_Handler = (void*) MCLK_Handler, /* 1 Main Clock */
.pfnOSCCTRL_0_Handler = (void*) OSCCTRL_0_Handler, /* 2 OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 */
.pfnOSCCTRL_1_Handler = (void*) OSCCTRL_1_Handler, /* 3 OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 */
.pfnOSCCTRL_2_Handler = (void*) OSCCTRL_2_Handler, /* 4 OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY */
.pfnOSCCTRL_3_Handler = (void*) OSCCTRL_3_Handler, /* 5 OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */
.pfnOSCCTRL_4_Handler = (void*) OSCCTRL_4_Handler, /* 6 OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 */
.pfnOSC32KCTRL_Handler = (void*) OSC32KCTRL_Handler, /* 7 32kHz Oscillators Control */
.pfnSUPC_0_Handler = (void*) SUPC_0_Handler, /* 8 SUPC_B12SRDY, SUPC_B33SRDY, SUPC_BOD12RDY, SUPC_BOD33RDY, SUPC_VCORERDY, SUPC_VREGRDY */
.pfnSUPC_1_Handler = (void*) SUPC_1_Handler, /* 9 SUPC_BOD12DET, SUPC_BOD33DET */
.pfnWDT_Handler = (void*) WDT_Handler, /* 10 Watchdog Timer */
.pfnRTC_Handler = (void*) RTC_Handler, /* 11 Real-Time Counter */
.pfnEIC_0_Handler = (void*) EIC_0_Handler, /* 12 EIC_EXTINT_0 */
.pfnEIC_1_Handler = (void*) EIC_1_Handler, /* 13 EIC_EXTINT_1 */
.pfnEIC_2_Handler = (void*) EIC_2_Handler, /* 14 EIC_EXTINT_2 */
.pfnEIC_3_Handler = (void*) EIC_3_Handler, /* 15 EIC_EXTINT_3 */
.pfnEIC_4_Handler = (void*) EIC_4_Handler, /* 16 EIC_EXTINT_4 */
.pfnEIC_5_Handler = (void*) EIC_5_Handler, /* 17 EIC_EXTINT_5 */
.pfnEIC_6_Handler = (void*) EIC_6_Handler, /* 18 EIC_EXTINT_6 */
.pfnEIC_7_Handler = (void*) EIC_7_Handler, /* 19 EIC_EXTINT_7 */
.pfnEIC_8_Handler = (void*) EIC_8_Handler, /* 20 EIC_EXTINT_8 */
.pfnEIC_9_Handler = (void*) EIC_9_Handler, /* 21 EIC_EXTINT_9 */
.pfnEIC_10_Handler = (void*) EIC_10_Handler, /* 22 EIC_EXTINT_10 */
.pfnEIC_11_Handler = (void*) EIC_11_Handler, /* 23 EIC_EXTINT_11 */
.pfnEIC_12_Handler = (void*) EIC_12_Handler, /* 24 EIC_EXTINT_12 */
.pfnEIC_13_Handler = (void*) EIC_13_Handler, /* 25 EIC_EXTINT_13 */
.pfnEIC_14_Handler = (void*) EIC_14_Handler, /* 26 EIC_EXTINT_14 */
.pfnEIC_15_Handler = (void*) EIC_15_Handler, /* 27 EIC_EXTINT_15 */
.pfnFREQM_Handler = (void*) FREQM_Handler, /* 28 Frequency Meter */
.pfnNVMCTRL_0_Handler = (void*) NVMCTRL_0_Handler, /* 29 NVMCTRL_0, NVMCTRL_1, NVMCTRL_2, NVMCTRL_3, NVMCTRL_4, NVMCTRL_5, NVMCTRL_6, NVMCTRL_7 */
.pfnNVMCTRL_1_Handler = (void*) NVMCTRL_1_Handler, /* 30 NVMCTRL_10, NVMCTRL_8, NVMCTRL_9 */
.pfnDMAC_0_Handler = (void*) DMAC_0_Handler, /* 31 DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 */
.pfnDMAC_1_Handler = (void*) DMAC_1_Handler, /* 32 DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 */
.pfnDMAC_2_Handler = (void*) DMAC_2_Handler, /* 33 DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 */
.pfnDMAC_3_Handler = (void*) DMAC_3_Handler, /* 34 DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 */
.pfnDMAC_4_Handler = (void*) DMAC_4_Handler, /* 35 DMAC_SUSP_10, DMAC_SUSP_11, DMAC_SUSP_12, DMAC_SUSP_13, DMAC_SUSP_14, DMAC_SUSP_15, DMAC_SUSP_16, DMAC_SUSP_17, DMAC_SUSP_18, DMAC_SUSP_19, DMAC_SUSP_20, DMAC_SUSP_21, DMAC_SUSP_22, DMAC_SUSP_23, DMAC_SUSP_24, DMAC_SUSP_25, DMAC_SUSP_26, DMAC_SUSP_27, DMAC_SUSP_28, DMAC_SUSP_29, DMAC_SUSP_30, DMAC_SUSP_31, DMAC_SUSP_4, DMAC_SUSP_5, DMAC_SUSP_6, DMAC_SUSP_7, DMAC_SUSP_8, DMAC_SUSP_9, DMAC_TCMPL_10, DMAC_TCMPL_11, DMAC_TCMPL_12, DMAC_TCMPL_13, DMAC_TCMPL_14, DMAC_TCMPL_15, DMAC_TCMPL_16, DMAC_TCMPL_17, DMAC_TCMPL_18, DMAC_TCMPL_19, DMAC_TCMPL_20, DMAC_TCMPL_21, DMAC_TCMPL_22, DMAC_TCMPL_23, DMAC_TCMPL_24, DMAC_TCMPL_25, DMAC_TCMPL_26, DMAC_TCMPL_27, DMAC_TCMPL_28, DMAC_TCMPL_29, DMAC_TCMPL_30, DMAC_TCMPL_31, DMAC_TCMPL_4, DMAC_TCMPL_5, DMAC_TCMPL_6, DMAC_TCMPL_7, DMAC_TCMPL_8, DMAC_TCMPL_9, DMAC_TERR_10, DMAC_TERR_11, DMAC_TERR_12, DMAC_TERR_13, DMAC_TERR_14, DMAC_TERR_15, DMAC_TERR_16, DMAC_TERR_17, DMAC_TERR_18, DMAC_TERR_19, DMAC_TERR_20, DMAC_TERR_21, DMAC_TERR_22, DMAC_TERR_23, DMAC_TERR_24, DMAC_TERR_25, DMAC_TERR_26, DMAC_TERR_27, DMAC_TERR_28, DMAC_TERR_29, DMAC_TERR_30, DMAC_TERR_31, DMAC_TERR_4, DMAC_TERR_5, DMAC_TERR_6, DMAC_TERR_7, DMAC_TERR_8, DMAC_TERR_9 */
.pfnEVSYS_0_Handler = (void*) EVSYS_0_Handler, /* 36 EVSYS_EVD_0, EVSYS_OVR_0 */
.pfnEVSYS_1_Handler = (void*) EVSYS_1_Handler, /* 37 EVSYS_EVD_1, EVSYS_OVR_1 */
.pfnEVSYS_2_Handler = (void*) EVSYS_2_Handler, /* 38 EVSYS_EVD_2, EVSYS_OVR_2 */
.pfnEVSYS_3_Handler = (void*) EVSYS_3_Handler, /* 39 EVSYS_EVD_3, EVSYS_OVR_3 */
.pfnEVSYS_4_Handler = (void*) EVSYS_4_Handler, /* 40 EVSYS_EVD_10, EVSYS_EVD_11, EVSYS_EVD_4, EVSYS_EVD_5, EVSYS_EVD_6, EVSYS_EVD_7, EVSYS_EVD_8, EVSYS_EVD_9, EVSYS_OVR_10, EVSYS_OVR_11, EVSYS_OVR_4, EVSYS_OVR_5, EVSYS_OVR_6, EVSYS_OVR_7, EVSYS_OVR_8, EVSYS_OVR_9 */
.pfnPAC_Handler = (void*) PAC_Handler, /* 41 Peripheral Access Controller */
.pfnTAL_0_Handler = (void*) TAL_0_Handler, /* 42 TAL_BRK */
.pfnTAL_1_Handler = (void*) TAL_1_Handler, /* 43 TAL_IPS_0, TAL_IPS_1 */
.pvReserved44 = (void*) (0UL), /* 44 Reserved */
.pfnRAMECC_Handler = (void*) RAMECC_Handler, /* 45 RAM ECC */
.pfnSERCOM0_0_Handler = (void*) SERCOM0_0_Handler, /* 46 SERCOM0_0 */
.pfnSERCOM0_1_Handler = (void*) SERCOM0_1_Handler, /* 47 SERCOM0_1 */
.pfnSERCOM0_2_Handler = (void*) SERCOM0_2_Handler, /* 48 SERCOM0_2 */
.pfnSERCOM0_3_Handler = (void*) SERCOM0_3_Handler, /* 49 SERCOM0_3, SERCOM0_4, SERCOM0_5, SERCOM0_6 */
.pfnSERCOM1_0_Handler = (void*) SERCOM1_0_Handler, /* 50 SERCOM1_0 */
.pfnSERCOM1_1_Handler = (void*) SERCOM1_1_Handler, /* 51 SERCOM1_1 */
.pfnSERCOM1_2_Handler = (void*) SERCOM1_2_Handler, /* 52 SERCOM1_2 */
.pfnSERCOM1_3_Handler = (void*) SERCOM1_3_Handler, /* 53 SERCOM1_3, SERCOM1_4, SERCOM1_5, SERCOM1_6 */
.pfnSERCOM2_0_Handler = (void*) SERCOM2_0_Handler, /* 54 SERCOM2_0 */
.pfnSERCOM2_1_Handler = (void*) SERCOM2_1_Handler, /* 55 SERCOM2_1 */
.pfnSERCOM2_2_Handler = (void*) SERCOM2_2_Handler, /* 56 SERCOM2_2 */
.pfnSERCOM2_3_Handler = (void*) SERCOM2_3_Handler, /* 57 SERCOM2_3, SERCOM2_4, SERCOM2_5, SERCOM2_6 */
.pfnSERCOM3_0_Handler = (void*) SERCOM3_0_Handler, /* 58 SERCOM3_0 */
.pfnSERCOM3_1_Handler = (void*) SERCOM3_1_Handler, /* 59 SERCOM3_1 */
.pfnSERCOM3_2_Handler = (void*) SERCOM3_2_Handler, /* 60 SERCOM3_2 */
.pfnSERCOM3_3_Handler = (void*) SERCOM3_3_Handler, /* 61 SERCOM3_3, SERCOM3_4, SERCOM3_5, SERCOM3_6 */
#ifdef ID_SERCOM4
.pfnSERCOM4_0_Handler = (void*) SERCOM4_0_Handler, /* 62 SERCOM4_0 */
.pfnSERCOM4_1_Handler = (void*) SERCOM4_1_Handler, /* 63 SERCOM4_1 */
.pfnSERCOM4_2_Handler = (void*) SERCOM4_2_Handler, /* 64 SERCOM4_2 */
.pfnSERCOM4_3_Handler = (void*) SERCOM4_3_Handler, /* 65 SERCOM4_3, SERCOM4_4, SERCOM4_5, SERCOM4_6 */
#else
.pvReserved62 = (void*) (0UL), /* 62 Reserved */
.pvReserved63 = (void*) (0UL), /* 63 Reserved */
.pvReserved64 = (void*) (0UL), /* 64 Reserved */
.pvReserved65 = (void*) (0UL), /* 65 Reserved */
#endif
#ifdef ID_SERCOM5
.pfnSERCOM5_0_Handler = (void*) SERCOM5_0_Handler, /* 66 SERCOM5_0 */
.pfnSERCOM5_1_Handler = (void*) SERCOM5_1_Handler, /* 67 SERCOM5_1 */
.pfnSERCOM5_2_Handler = (void*) SERCOM5_2_Handler, /* 68 SERCOM5_2 */
.pfnSERCOM5_3_Handler = (void*) SERCOM5_3_Handler, /* 69 SERCOM5_3, SERCOM5_4, SERCOM5_5, SERCOM5_6 */
#else
.pvReserved66 = (void*) (0UL), /* 66 Reserved */
.pvReserved67 = (void*) (0UL), /* 67 Reserved */
.pvReserved68 = (void*) (0UL), /* 68 Reserved */
.pvReserved69 = (void*) (0UL), /* 69 Reserved */
#endif
#ifdef ID_SERCOM6
.pfnSERCOM6_0_Handler = (void*) SERCOM6_0_Handler, /* 70 SERCOM6_0 */
.pfnSERCOM6_1_Handler = (void*) SERCOM6_1_Handler, /* 71 SERCOM6_1 */
.pfnSERCOM6_2_Handler = (void*) SERCOM6_2_Handler, /* 72 SERCOM6_2 */
.pfnSERCOM6_3_Handler = (void*) SERCOM6_3_Handler, /* 73 SERCOM6_3, SERCOM6_4, SERCOM6_5, SERCOM6_6 */
#else
.pvReserved70 = (void*) (0UL), /* 70 Reserved */
.pvReserved71 = (void*) (0UL), /* 71 Reserved */
.pvReserved72 = (void*) (0UL), /* 72 Reserved */
.pvReserved73 = (void*) (0UL), /* 73 Reserved */
#endif
#ifdef ID_SERCOM7
.pfnSERCOM7_0_Handler = (void*) SERCOM7_0_Handler, /* 74 SERCOM7_0 */
.pfnSERCOM7_1_Handler = (void*) SERCOM7_1_Handler, /* 75 SERCOM7_1 */
.pfnSERCOM7_2_Handler = (void*) SERCOM7_2_Handler, /* 76 SERCOM7_2 */
.pfnSERCOM7_3_Handler = (void*) SERCOM7_3_Handler, /* 77 SERCOM7_3, SERCOM7_4, SERCOM7_5, SERCOM7_6 */
#else
.pvReserved74 = (void*) (0UL), /* 74 Reserved */
.pvReserved75 = (void*) (0UL), /* 75 Reserved */
.pvReserved76 = (void*) (0UL), /* 76 Reserved */
.pvReserved77 = (void*) (0UL), /* 77 Reserved */
#endif
#ifdef ID_CAN0
.pfnCAN0_Handler = (void*) CAN0_Handler, /* 78 Control Area Network 0 */
#else
.pvReserved78 = (void*) (0UL), /* 78 Reserved */
#endif
#ifdef ID_CAN1
.pfnCAN1_Handler = (void*) CAN1_Handler, /* 79 Control Area Network 1 */
#else
.pvReserved79 = (void*) (0UL), /* 79 Reserved */
#endif
#ifdef ID_USB
.pfnUSB_0_Handler = (void*) USB_0_Handler, /* 80 USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
.pfnUSB_1_Handler = (void*) USB_1_Handler, /* 81 USB_SOF_HSOF */
.pfnUSB_2_Handler = (void*) USB_2_Handler, /* 82 USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */
.pfnUSB_3_Handler = (void*) USB_3_Handler, /* 83 USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */
#else
.pvReserved80 = (void*) (0UL), /* 80 Reserved */
.pvReserved81 = (void*) (0UL), /* 81 Reserved */
.pvReserved82 = (void*) (0UL), /* 82 Reserved */
.pvReserved83 = (void*) (0UL), /* 83 Reserved */
#endif
#ifdef ID_GMAC
.pfnGMAC_Handler = (void*) GMAC_Handler, /* 84 Ethernet MAC */
#else
.pvReserved84 = (void*) (0UL), /* 84 Reserved */
#endif
.pfnTCC0_0_Handler = (void*) TCC0_0_Handler, /* 85 TCC0_CNT_A, TCC0_DFS_A, TCC0_ERR_A, TCC0_FAULT0_A, TCC0_FAULT1_A, TCC0_FAULTA_A, TCC0_FAULTB_A, TCC0_OVF, TCC0_TRG, TCC0_UFS_A */
.pfnTCC0_1_Handler = (void*) TCC0_1_Handler, /* 86 TCC0_MC_0 */
.pfnTCC0_2_Handler = (void*) TCC0_2_Handler, /* 87 TCC0_MC_1 */
.pfnTCC0_3_Handler = (void*) TCC0_3_Handler, /* 88 TCC0_MC_2 */
.pfnTCC0_4_Handler = (void*) TCC0_4_Handler, /* 89 TCC0_MC_3 */
.pfnTCC0_5_Handler = (void*) TCC0_5_Handler, /* 90 TCC0_MC_4 */
.pfnTCC0_6_Handler = (void*) TCC0_6_Handler, /* 91 TCC0_MC_5 */
.pfnTCC1_0_Handler = (void*) TCC1_0_Handler, /* 92 TCC1_CNT_A, TCC1_DFS_A, TCC1_ERR_A, TCC1_FAULT0_A, TCC1_FAULT1_A, TCC1_FAULTA_A, TCC1_FAULTB_A, TCC1_OVF, TCC1_TRG, TCC1_UFS_A */
.pfnTCC1_1_Handler = (void*) TCC1_1_Handler, /* 93 TCC1_MC_0 */
.pfnTCC1_2_Handler = (void*) TCC1_2_Handler, /* 94 TCC1_MC_1 */
.pfnTCC1_3_Handler = (void*) TCC1_3_Handler, /* 95 TCC1_MC_2 */
.pfnTCC1_4_Handler = (void*) TCC1_4_Handler, /* 96 TCC1_MC_3 */
.pfnTCC2_0_Handler = (void*) TCC2_0_Handler, /* 97 TCC2_CNT_A, TCC2_DFS_A, TCC2_ERR_A, TCC2_FAULT0_A, TCC2_FAULT1_A, TCC2_FAULTA_A, TCC2_FAULTB_A, TCC2_OVF, TCC2_TRG, TCC2_UFS_A */
.pfnTCC2_1_Handler = (void*) TCC2_1_Handler, /* 98 TCC2_MC_0 */
.pfnTCC2_2_Handler = (void*) TCC2_2_Handler, /* 99 TCC2_MC_1 */
.pfnTCC2_3_Handler = (void*) TCC2_3_Handler, /* 100 TCC2_MC_2 */
#ifdef ID_TCC3
.pfnTCC3_0_Handler = (void*) TCC3_0_Handler, /* 101 TCC3_CNT_A, TCC3_DFS_A, TCC3_ERR_A, TCC3_FAULT0_A, TCC3_FAULT1_A, TCC3_FAULTA_A, TCC3_FAULTB_A, TCC3_OVF, TCC3_TRG, TCC3_UFS_A */
.pfnTCC3_1_Handler = (void*) TCC3_1_Handler, /* 102 TCC3_MC_0 */
.pfnTCC3_2_Handler = (void*) TCC3_2_Handler, /* 103 TCC3_MC_1 */
#else
.pvReserved101 = (void*) (0UL), /* 101 Reserved */
.pvReserved102 = (void*) (0UL), /* 102 Reserved */
.pvReserved103 = (void*) (0UL), /* 103 Reserved */
#endif
#ifdef ID_TCC4
.pfnTCC4_0_Handler = (void*) TCC4_0_Handler, /* 104 TCC4_CNT_A, TCC4_DFS_A, TCC4_ERR_A, TCC4_FAULT0_A, TCC4_FAULT1_A, TCC4_FAULTA_A, TCC4_FAULTB_A, TCC4_OVF, TCC4_TRG, TCC4_UFS_A */
.pfnTCC4_1_Handler = (void*) TCC4_1_Handler, /* 105 TCC4_MC_0 */
.pfnTCC4_2_Handler = (void*) TCC4_2_Handler, /* 106 TCC4_MC_1 */
#else
.pvReserved104 = (void*) (0UL), /* 104 Reserved */
.pvReserved105 = (void*) (0UL), /* 105 Reserved */
.pvReserved106 = (void*) (0UL), /* 106 Reserved */
#endif
.pfnTC0_Handler = (void*) TC0_Handler, /* 107 Basic Timer Counter 0 */
.pfnTC1_Handler = (void*) TC1_Handler, /* 108 Basic Timer Counter 1 */
.pfnTC2_Handler = (void*) TC2_Handler, /* 109 Basic Timer Counter 2 */
.pfnTC3_Handler = (void*) TC3_Handler, /* 110 Basic Timer Counter 3 */
#ifdef ID_TC4
.pfnTC4_Handler = (void*) TC4_Handler, /* 111 Basic Timer Counter 4 */
#else
.pvReserved111 = (void*) (0UL), /* 111 Reserved */
#endif
#ifdef ID_TC5
.pfnTC5_Handler = (void*) TC5_Handler, /* 112 Basic Timer Counter 5 */
#else
.pvReserved112 = (void*) (0UL), /* 112 Reserved */
#endif
#ifdef ID_TC6
.pfnTC6_Handler = (void*) TC6_Handler, /* 113 Basic Timer Counter 6 */
#else
.pvReserved113 = (void*) (0UL), /* 113 Reserved */
#endif
#ifdef ID_TC7
.pfnTC7_Handler = (void*) TC7_Handler, /* 114 Basic Timer Counter 7 */
#else
.pvReserved114 = (void*) (0UL), /* 114 Reserved */
#endif
.pfnPDEC_0_Handler = (void*) PDEC_0_Handler, /* 115 PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A */
.pfnPDEC_1_Handler = (void*) PDEC_1_Handler, /* 116 PDEC_MC_0 */
.pfnPDEC_2_Handler = (void*) PDEC_2_Handler, /* 117 PDEC_MC_1 */
.pfnADC0_0_Handler = (void*) ADC0_0_Handler, /* 118 ADC0_OVERRUN, ADC0_WINMON */
.pfnADC0_1_Handler = (void*) ADC0_1_Handler, /* 119 ADC0_RESRDY */
.pfnADC1_0_Handler = (void*) ADC1_0_Handler, /* 120 ADC1_OVERRUN, ADC1_WINMON */
.pfnADC1_1_Handler = (void*) ADC1_1_Handler, /* 121 ADC1_RESRDY */
.pfnAC_Handler = (void*) AC_Handler, /* 122 Analog Comparators */
.pfnDAC_0_Handler = (void*) DAC_0_Handler, /* 123 DAC_OVERRUN_A_0, DAC_OVERRUN_A_1, DAC_UNDERRUN_A_0, DAC_UNDERRUN_A_1 */
.pfnDAC_1_Handler = (void*) DAC_1_Handler, /* 124 DAC_EMPTY_0 */
.pfnDAC_2_Handler = (void*) DAC_2_Handler, /* 125 DAC_EMPTY_1 */
.pfnDAC_3_Handler = (void*) DAC_3_Handler, /* 126 DAC_RESRDY_0 */
.pfnDAC_4_Handler = (void*) DAC_4_Handler, /* 127 DAC_RESRDY_1 */
#ifdef ID_I2S
.pfnI2S_Handler = (void*) I2S_Handler, /* 128 Inter-IC Sound Interface */
#else
.pvReserved128 = (void*) (0UL), /* 128 Reserved */
#endif
.pfnPCC_Handler = (void*) PCC_Handler, /* 129 Parallel Capture Controller */
.pfnAES_Handler = (void*) AES_Handler, /* 130 Advanced Encryption Standard */
.pfnTRNG_Handler = (void*) TRNG_Handler, /* 131 True Random Generator */
#ifdef ID_ICM
.pfnICM_Handler = (void*) ICM_Handler, /* 132 Integrity Check Monitor */
#else
.pvReserved132 = (void*) (0UL), /* 132 Reserved */
#endif
#ifdef ID_PUKCC
.pfnPUKCC_Handler = (void*) PUKCC_Handler, /* 133 PUblic-Key Cryptography Controller */
#else
.pvReserved133 = (void*) (0UL), /* 133 Reserved */
#endif
.pfnQSPI_Handler = (void*) QSPI_Handler, /* 134 Quad SPI interface */
#ifdef ID_SDHC0
.pfnSDHC0_Handler = (void*) SDHC0_Handler, /* 135 SD/MMC Host Controller 0 */
#else
.pvReserved135 = (void*) (0UL), /* 135 Reserved */
#endif
#ifdef ID_SDHC1
.pfnSDHC1_Handler = (void*) SDHC1_Handler /* 136 SD/MMC Host Controller 1 */
#else
.pvReserved136 = (void*) (0UL) /* 136 Reserved */
#endif
};
/**
* \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine.
*/
void Reset_Handler(void)
{
uint32_t *pSrc, *pDest;
/* Initialize the relocate segment */
pSrc = &_etext;
pDest = &_srelocate;
if (pSrc != pDest) {
for (; pDest < &_erelocate;) {
*pDest++ = *pSrc++;
}
}
/* Clear the zero segment */
for (pDest = &_szero; pDest < &_ezero;) {
*pDest++ = 0;
}
/* Set the vector table base address */
pSrc = (uint32_t *) & _sfixed;
SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);
#if __FPU_USED
/* Enable FPU */
SCB->CPACR |= (0xFu << 20);
__DSB();
__ISB();
#endif
/* Initialize the C library */
__libc_init_array();
/* Branch to main function */
main();
/* Infinite loop */
while (1);
}
/**
* \brief Default interrupt handler for unused IRQs.
*/
void Dummy_Handler(void)
{
while (1) {
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,163 @@
/**
* \file
*
* \brief USB configuration file
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _CONF_USB_H_
#define _CONF_USB_H_
#include "compiler.h"
#include "udi_device_conf.h"
#define UDI_CDC_DEFAULT_RATE 115200
#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1
#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
#define UDI_CDC_DEFAULT_DATABITS 8
//! Device definition (mandatory)
#define USB_DEVICE_VENDOR_ID VENDOR_ID
#define USB_DEVICE_PRODUCT_ID PRODUCT_ID
#define USB_DEVICE_VERSION DEVICE_VER
#define USB_DEVICE_POWER 500 // Consumption on Vbus line (mA)
#define USB_DEVICE_ATTR (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED)
// (USB_CONFIG_ATTR_SELF_POWERED)
// (USB_CONFIG_ATTR_BUS_POWERED)
//! USB Device string definitions (Optional)
#define USB_DEVICE_MANUFACTURE_NAME MANUFACTURER
#define USB_DEVICE_PRODUCT_NAME PRODUCT
#define USB_DEVICE_SERIAL_NAME SERIAL_NUM
//Comment out USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL to prevent ROM lookup of factory programmed serial number
#define USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL
/**
* Device speeds support
* @{
*/
//! To define a Low speed device
//#define USB_DEVICE_LOW_SPEED
//! To authorize the High speed
#if (UC3A3||UC3A4)
//#define USB_DEVICE_HS_SUPPORT
#elif (SAM3XA||SAM3U)
//#define USB_DEVICE_HS_SUPPORT
#endif
//@}
/**
* USB Device Callbacks definitions (Optional)
* @{
*/
#define UDC_VBUS_EVENT(b_vbus_high)
#define UDC_SOF_EVENT() main_sof_action()
#define UDC_SUSPEND_EVENT() main_suspend_action()
#define UDC_RESUME_EVENT() main_resume_action()
//! Mandatory when USB_DEVICE_ATTR authorizes remote wakeup feature
#define UDC_REMOTEWAKEUP_ENABLE() main_remotewakeup_enable()
#define UDC_REMOTEWAKEUP_DISABLE() main_remotewakeup_disable()
//! When a extra string descriptor must be supported
//! other than manufacturer, product and serial string
// #define UDC_GET_EXTRA_STRING()
//@}
//@}
/**
* USB Interface Configuration
* @{
*/
/**
* Configuration of HID Keyboard interface
* @{
*/
//! Interface callback definition
#ifdef KBD
#define UDI_HID_KBD_ENABLE_EXT() main_kbd_enable()
#define UDI_HID_KBD_DISABLE_EXT() main_kbd_disable()
//#define UDI_HID_KBD_CHANGE_LED(value) ui_kbd_led(value)
#endif
#ifdef NKRO
#define UDI_HID_NKRO_ENABLE_EXT() main_nkro_enable()
#define UDI_HID_NKRO_DISABLE_EXT() main_nkro_disable()
//#define UDI_HID_NKRO_CHANGE_LED(value) ui_kbd_led(value)
#endif
#ifdef EXK
#define UDI_HID_EXK_ENABLE_EXT() main_exk_enable()
#define UDI_HID_EXK_DISABLE_EXT() main_exk_disable()
#endif
#ifdef MOU
#define UDI_HID_MOU_ENABLE_EXT() main_mou_enable()
#define UDI_HID_MOU_DISABLE_EXT() main_mou_disable()
#endif
#ifdef RAW
#define UDI_HID_RAW_ENABLE_EXT() main_raw_enable()
#define UDI_HID_RAW_DISABLE_EXT() main_raw_disable()
#endif
//@}
//@}
/**
* USB Device Driver Configuration
* @{
*/
//@}
//! The includes of classes and other headers must be done at the end of this file to avoid compile error
#include "udi_hid_kbd_conf.h"
#include "usb_main.h"
#include "ui.h"
#endif // _CONF_USB_H_

View File

@ -0,0 +1,118 @@
/*
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/>.
*/
#include "samd51j18a.h"
#include "conf_usb.h"
#include "udd.h"
uint8_t keyboard_protocol = 1;
void main_suspend_action(void)
{
ui_powerdown();
}
void main_resume_action(void)
{
ui_wakeup();
}
void main_sof_action(void)
{
ui_process(udd_get_frame_number());
}
void main_remotewakeup_enable(void)
{
ui_wakeup_enable();
}
void main_remotewakeup_disable(void)
{
ui_wakeup_disable();
}
#ifdef KBD
volatile bool main_b_kbd_enable = false;
bool main_kbd_enable(void)
{
main_b_kbd_enable = true;
return true;
}
void main_kbd_disable(void)
{
main_b_kbd_enable = false;
}
#endif
#ifdef NKRO
volatile bool main_b_nkro_enable = false;
bool main_nkro_enable(void)
{
main_b_nkro_enable = true;
return true;
}
void main_nkro_disable(void)
{
main_b_nkro_enable = false;
}
#endif
#ifdef EXK
volatile bool main_b_exk_enable = false;
bool main_exk_enable(void)
{
main_b_exk_enable = true;
return true;
}
void main_exk_disable(void)
{
main_b_exk_enable = false;
}
#endif
#ifdef MOU
volatile bool main_b_mou_enable = false;
bool main_mou_enable(void)
{
main_b_mou_enable = true;
return true;
}
void main_mou_disable(void)
{
main_b_mou_enable = false;
}
#endif
#ifdef RAW
volatile bool main_b_raw_enable = false;
bool main_raw_enable(void)
{
main_b_raw_enable = true;
return true;
}
void main_raw_disable(void)
{
main_b_raw_enable = false;
}
#endif

View File

@ -0,0 +1,268 @@
#include "samd51j18a.h"
#include "stdarg.h"
#include "spfssf.h"
#include "usb_util.h"
int vspf(char *_Dest, const char *_Format, va_list va)
{
//va_list va; //Variable argument list variable
char *d = _Dest; //Pointer to dest
//va_start(va,_Format); //Initialize the variable argument list
while (*_Format) //While not end of format string
{
if (*_Format == SPF_SPEC_START) //If current format string character is the specifier start character
{
_Format++; //Skip over the character
while (*_Format && *_Format <= 64) _Format++; //Forward past any options
if (*_Format == SPF_SPEC_START) *d++ = *_Format; //If the character is the specifier start character, output the character and advance dest
else if (*_Format == SPF_SPEC_LONG) //If the character is the long type
{
_Format++; //Skip over the character
if (*_Format == SPF_SPEC_DECIMAL) //If the character is the decimal type
{
int64_t buf = va_arg(va,int64_t); //Get the next value from the va list
//if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and invert number
//spf_uint2str_32_3t(&d,buf,32); //Perform the conversion
d += UTIL_ltoa_radix(buf, d, 10);
}
else if (*_Format == SPF_SPEC_UNSIGNED) //If the character is the unsigned type
{
uint64_t num = va_arg(va,uint64_t); //Get the next value from the va list
//spf_uint2str_32_3t(&d,num,32); //Perform the conversion
d += UTIL_ltoa_radix(num, d, 10);
}
else if (*_Format == SPF_SPEC_UHINT || *_Format == SPF_SPEC_UHINT_UP) //If the character is the unsigned type
{
uint64_t buf = va_arg(va,uint64_t); //Get the next value from the va list
//spf_uint2hex_32(&d,(unsigned long) buf);
d += UTIL_ltoa_radix(buf, d, 16);
}
else //If the character was not a known type
{
*d++ = SPF_SPEC_START; //Output the start specifier
*d++ = SPF_SPEC_LONG; //Output the long type
*d++ = *_Format; //Output the unknown type
}
}
else if (*_Format == SPF_SPEC_DECIMAL) //If the character is the decimal type
{
int buf = va_arg(va,int); //Get the next value from the va list
//if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and invert number
//spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
d += UTIL_itoa(buf, d);
}
else if (*_Format == SPF_SPEC_INT) //If the character is the integer type
{
int buf = va_arg(va,int); //Get the next value from the va list
//if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and inverted number
//spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
d += UTIL_itoa(buf, d);
}
else if (*_Format == SPF_SPEC_UINT) //If the character is the unsigned integer type
{
int buf = va_arg(va,int); //Get the next value from the va list
//spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
d += UTIL_utoa(buf, d);
}
else if (*_Format == SPF_SPEC_STRING) //If the character is the string type
{
char *buf = va_arg(va,char*); //Get the next value from the va list
while (*buf) *d++ = *buf++; //Perform the conversion (simply output characters and adcance pointers)
}
else if (*_Format == SPF_SPEC_UHINT || *_Format == SPF_SPEC_UHINT_UP) //If the character is the short type
{
int buf = va_arg(va,unsigned int); //Get the next value from the va list
//spf_uint2hex_32(&d,(unsigned long) buf); //Perform the conversion
d += UTIL_utoa(buf, d);
}
else //If the character type is unknown
{
*d++ = SPF_SPEC_START; //Output the start specifier
*d++ = *_Format; //Output the unknown type
}
}
else *d++ = *_Format; //If the character is unknown, output it to dest and advance dest
_Format++; //Advance the format buffer pointer to next character
}
//va_end(va); //End the variable argument list
*d = '\0'; //Cap off the destination string with a zero
return d - _Dest; //Return the length of the destintion buffer
}
int spf(char *_Dest, const char *_Format, ...)
{
va_list va; //Variable argument list variable
int result;
va_start(va,_Format); //Initialize the variable argument list
result = vspf(_Dest, _Format, va);
va_end(va);
return result;
}
//sscanf string to number (integer types)
int64_t ssf_ston(const char **_Src, uint32_t count, uint32_t *conv_count)
{
int64_t value = 0; //Return value accumulator
uint32_t counter=count; //Counter to keep track of numbers converted
const char* p; //Pointer to first non space character
while (*(*_Src) == SSF_SKIP_SPACE) (*_Src)++; //Forward through the whitespace to next non whitespace
p = (*_Src); //Set pointer to first non space character
if (*p == '+' || *p == '-') (*_Src)++; //Skip over sign if any
while (*(*_Src) >= ASCII_NUM_START &&
*(*_Src) <= ASCII_NUM_END &&
counter) //While the source character is a digit and counter is not zero
{
value *= 10; //Multiply result by 10 to make room for next 1's place number
value += *(*_Src)++ - ASCII_NUM_START; //Add source number to value
counter--; //Decrement counter
}
if (counter - count == 0) return 0; //If no number conversion were performed, return 0
if (*p == '-') value = -value; //If the number given was negative, make the result negative
if (conv_count) (*conv_count)++; //Increment the converted count
return value; //Return the value
}
uint64_t ssf_hton(const char **_Src, uint32_t count,uint32_t *conv_count)
{
int64_t value=0; //Return value accumulator
uint32_t counter=count; //Counter to keep track of numbers converted
//const char* p; //Pointer to first non space character
char c;
while (*(*_Src) == SSF_SKIP_SPACE) (*_Src)++; //Forward through the whitespace to next non whitespace
//p = (*_Src); //Set pointer to first non space character
while (counter)
{
c = *(*_Src)++;
if (c >= 'a' && c <= 'f') c -= ('a'-'A'); //toupper
if (c < '0' || (c > '9' && c < 'A') || c > 'F') break;
value *= 16; //Multiply result by 10 to make room for next 1's place number
c = c - '0';
if (c > 9) c -= 7;
value += c; //Add source number to value
counter--; //Decrement counter
}
if (counter - count == 0) return 0; //If no number conversion were performed, return 0
//if (*p == '-') value = -value; //If the number given was negative, make the result negative
if (conv_count) (*conv_count)++; //Increment the converted count
return value;
}
//sscanf
int ssf(const char *_Src, const char *_Format, ...)
{
va_list va; //Variable argument list variable
unsigned char looking_for=0; //Static char specified in format to be found in source
uint32_t conv_count=0; //Count of conversions made
va_start(va,_Format); //Initialize the variable argument list
while (*_Format) //While the format string has not been fully read
{
if (looking_for != 0) //If we are looking for a matching character in the source string
{
while (*_Src != looking_for && *_Src) _Src++; //While the character is not found in the source string and not the end of the source
// string, increment the pointer position
if (*_Src == looking_for) _Src++; //If the character was found, step over it
else break; //Else the end was reached and the scan is now invalid (Could not find static character)
looking_for = 0; //Clear the looking for character
}
if (*_Format == SSF_SPEC_START) //If the current format character is the specifier start character
{
_Format++; //Step over the specifier start character
if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
{
int *value=va_arg(va,int*); //User given destination address
//*value = (int)ssf_ston(&_Src,5,&conv_count); //Run conversion
*value = (int)ssf_ston(&_Src,10,&conv_count); //Run conversion
}
else if (*_Format == SSF_SPEC_LONG) //If the long specifier type is found
{
_Format++; //Skip over the specifier type
if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
{
int64_t *value=va_arg(va,int64_t*); //User given destination address
//*value = (int64_t)ssf_ston(&_Src,10,&conv_count); //Run conversion
*value = (int64_t)ssf_ston(&_Src,19,&conv_count); //Run conversion
}
else if (*_Format == SSF_SPEC_UHINT) //If the decimal specifier type is found
{
uint64_t *value=va_arg(va,uint64_t *); //User given destination address
//*value = (uint64_t int)ssf_hton(&_Src,12,&conv_count); //Run conversion
*value = (uint64_t)ssf_hton(&_Src,16,&conv_count); //Run conversion
}
}
else if (*_Format == SSF_SPEC_SHORTINT) //If the short int specifier type is found
{
_Format++; //Skip over the specifier type
if (*_Format == SSF_SPEC_SHORTINT) //If the short int specifier type is found
{
_Format++; //Skip over the specifier type
if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
{
unsigned char *value=va_arg(va,unsigned char*); //User given destination address
//*value = (unsigned char)ssf_ston(&_Src,3,&conv_count); //Run conversion
*value = (unsigned char)ssf_ston(&_Src,5,&conv_count); //Run conversion
}
}
}
else if (*_Format == SSF_SPEC_STRING) //If the specifier type is string
{
char *value=va_arg(va,char*); //User given destination address, max chars read pointer
while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
while (*_Src != SSF_SKIP_SPACE && *_Src) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
*value = 0; //Cap off the string pointer with zero
conv_count++; //Increment the converted count
}
else if (*_Format == SSF_SPEC_VERSION) //If the specifier type is string
{
char *value=va_arg(va,char*); //User given destination address, max chars read pointer
while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
while (*_Src != SSF_DELIM_COMMA && *_Src) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
*value = 0; //Cap off the string pointer with zero
conv_count++; //Increment the converted count
}
else if (*_Format >= ASCII_NUM_START && *_Format <= ASCII_NUM_END)
{
uint32_t len = (uint32_t)ssf_ston(&_Format,3,NULL); //Convert the given length
if (*_Format == SSF_SPEC_STRING) //If the specifier type is string
{
char *value=va_arg(va,char*),*e; //User given destination address, max chars read pointer
while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
e = (char*)_Src+len; //Set a maximum length pointer location
while (*_Src != SSF_SKIP_SPACE && *_Src && _Src != e) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
*value = 0; //Cap off the string pointer with zero
conv_count++; //Increment the converted count
}
else if (*_Format == SSF_SPEC_VERSION) //If the specifier type is string
{
char *value=va_arg(va,char*),*e; //User given destination address, max chars read pointer
while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
e = (char*)_Src+len; //Set a maximum length pointer location
while (*_Src != SSF_DELIM_COMMA && *_Src && _Src != e) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
*value = 0; //Cap off the string pointer with zero
conv_count++; //Increment the converted count
}
}
else if (*_Format == SSF_SPEC_START) looking_for = *_Format; //If another start specifier character is found, output a specifier character
else break; //Scan is now invalid (Uknown type specified)
}
else if (*_Format == SSF_SKIP_SPACE) { } //If a space is found, ignore it
else looking_for = *_Format; //If any other character is found, it is static and should be found in src as well
_Format++; //Skip over current format character
}
va_end(va); //End the variable argument list
return conv_count; //Return the number of conversions made
}

View File

@ -0,0 +1,57 @@
#ifndef ____spfssf_h
#define ____spfssf_h
#include <stdarg.h>
#define sprintf spf
#define sscanf ssf
#define SIZEOF_OFFSET 1
#ifndef NULL
#define NULL 0
#endif
#define SPF_NONE 0
#define SPF_SPEC_START 37 //%
#define SPF_SPEC_DECIMAL 100 //d 16bit dec signed (-32767 to 32767) DONE same as i
#define SPF_SPEC_INT 105 //i 16bit dec signed (-32767 to 32767) DONE same as d
#define SPF_SPEC_UINT 117 //u 16bit dec unsigned (0 to 65535) DONE
#define SPF_SPEC_STRING 115 //s variable length (abcd...) DONE
#define SPF_SPEC_UHINT 120 //x 16bit hex lwrc (7fa) DONE
#define SPF_SPEC_UHINT_UP 88 //x 16bit hex lwrc (7fa) DONE
#define SPF_SPEC_LONG 108 //l start of either ld or lu DONE
#define SPF_SPEC_DECIMAL 100 //ld 32bit dec signed (-2147483647 to 2147483647) DONE
#define SPF_SPEC_UNSIGNED 117 //lu 32bit dec unsigned (0 to 4294967295) DONE
#define SPF_SPEC_UHINT 120 //lx 32bit hex unsigned (0 to ffffffff) DONE
#define SSF_SPEC_START 37 //%
#define SSF_SPEC_SHORTINT 104 //h 8bit dec signed (-127 to 127) DONE
#define SSF_LEN_SHORTINT 3 //hhd
#define SSF_SPEC_DECIMAL 100 //d 16bit dec signed (-32767 to 32767) DONE
#define SSF_LEN_DECIMAL 5 //32767
#define SSF_SPEC_INT 105 //i 16bit dec signed (-32767 to 32767) DONE
#define SSF_LEN_INT 5 //32767
#define SSF_SPEC_LONG 108 //l start of either ld or lu DONE
#define SSF_SPEC_DECIMAL 100 //ld 32bit dec signed (-2147483647 to 2147483647) DONE
#define SSF_SPEC_UHINT 120 //lx 32bit hex unsigned DONE
#define SSF_LEN_LDECIMAL 10 //2147483647
#define SSF_SPEC_STRING 115 //s variable length (abcd...) DONE
#define SSF_SKIP_SPACE 32 //space
#define SSF_SPEC_VERSION 118 //v collect to comma delimiter - special
#define SSF_DELIM_COMMA 44 //,
#define ASCII_NUM_START 48 //0
#define ASCII_NUM_END 58 //9
#define T_UINT32_0_LIMIT 14
#define T_UINT32_1_LIMIT 27
int vspf(char *_Dest, const char *_Format, va_list va);
int spf(char *_Dest, const char *_Format, ...);
int ssf(const char *_Src, const char *_Format, ...);
#endif //____spfssf_h

View File

@ -0,0 +1,158 @@
/**
* \file
*
* \brief Status code definitions.
*
* This file defines various status codes returned by functions,
* indicating success or failure as well as what kind of failure.
*
* Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef STATUS_CODES_H_INCLUDED
#define STATUS_CODES_H_INCLUDED
#include <stdint.h>
/**
* \defgroup group_sam0_utils_status_codes Status Codes
*
* \ingroup group_sam0_utils
*
* @{
*/
/** Mask to retrieve the error category of a status code. */
#define STATUS_CATEGORY_MASK 0xF0
/** Mask to retrieve the error code within the category of a status code. */
#define STATUS_ERROR_MASK 0x0F
/** Status code error categories. */
enum status_categories {
STATUS_CATEGORY_OK = 0x00,
STATUS_CATEGORY_COMMON = 0x10,
STATUS_CATEGORY_ANALOG = 0x30,
STATUS_CATEGORY_COM = 0x40,
STATUS_CATEGORY_IO = 0x50,
};
/**
* Status code that may be returned by shell commands and protocol
* implementations.
*
* \note Any change to these status codes and the corresponding
* message strings is strictly forbidden. New codes can be added,
* however, but make sure that any message string tables are updated
* at the same time.
*/
enum status_code {
STATUS_OK = STATUS_CATEGORY_OK | 0x00,
STATUS_VALID_DATA = STATUS_CATEGORY_OK | 0x01,
STATUS_NO_CHANGE = STATUS_CATEGORY_OK | 0x02,
STATUS_ABORTED = STATUS_CATEGORY_OK | 0x04,
STATUS_BUSY = STATUS_CATEGORY_OK | 0x05,
STATUS_SUSPEND = STATUS_CATEGORY_OK | 0x06,
STATUS_ERR_IO = STATUS_CATEGORY_COMMON | 0x00,
STATUS_ERR_REQ_FLUSHED = STATUS_CATEGORY_COMMON | 0x01,
STATUS_ERR_TIMEOUT = STATUS_CATEGORY_COMMON | 0x02,
STATUS_ERR_BAD_DATA = STATUS_CATEGORY_COMMON | 0x03,
STATUS_ERR_NOT_FOUND = STATUS_CATEGORY_COMMON | 0x04,
STATUS_ERR_UNSUPPORTED_DEV = STATUS_CATEGORY_COMMON | 0x05,
STATUS_ERR_NO_MEMORY = STATUS_CATEGORY_COMMON | 0x06,
STATUS_ERR_INVALID_ARG = STATUS_CATEGORY_COMMON | 0x07,
STATUS_ERR_BAD_ADDRESS = STATUS_CATEGORY_COMMON | 0x08,
STATUS_ERR_BAD_FORMAT = STATUS_CATEGORY_COMMON | 0x0A,
STATUS_ERR_BAD_FRQ = STATUS_CATEGORY_COMMON | 0x0B,
STATUS_ERR_DENIED = STATUS_CATEGORY_COMMON | 0x0c,
STATUS_ERR_ALREADY_INITIALIZED = STATUS_CATEGORY_COMMON | 0x0d,
STATUS_ERR_OVERFLOW = STATUS_CATEGORY_COMMON | 0x0e,
STATUS_ERR_NOT_INITIALIZED = STATUS_CATEGORY_COMMON | 0x0f,
STATUS_ERR_SAMPLERATE_UNAVAILABLE = STATUS_CATEGORY_ANALOG | 0x00,
STATUS_ERR_RESOLUTION_UNAVAILABLE = STATUS_CATEGORY_ANALOG | 0x01,
STATUS_ERR_BAUDRATE_UNAVAILABLE = STATUS_CATEGORY_COM | 0x00,
STATUS_ERR_PACKET_COLLISION = STATUS_CATEGORY_COM | 0x01,
STATUS_ERR_PROTOCOL = STATUS_CATEGORY_COM | 0x02,
STATUS_ERR_PIN_MUX_INVALID = STATUS_CATEGORY_IO | 0x00,
};
typedef enum status_code status_code_genare_t;
/**
Status codes used by MAC stack.
*/
enum status_code_wireless {
//STATUS_OK = 0, //!< Success
ERR_IO_ERROR = -1, //!< I/O error
ERR_FLUSHED = -2, //!< Request flushed from queue
ERR_TIMEOUT = -3, //!< Operation timed out
ERR_BAD_DATA = -4, //!< Data integrity check failed
ERR_PROTOCOL = -5, //!< Protocol error
ERR_UNSUPPORTED_DEV = -6, //!< Unsupported device
ERR_NO_MEMORY = -7, //!< Insufficient memory
ERR_INVALID_ARG = -8, //!< Invalid argument
ERR_BAD_ADDRESS = -9, //!< Bad address
ERR_BUSY = -10, //!< Resource is busy
ERR_BAD_FORMAT = -11, //!< Data format not recognized
ERR_NO_TIMER = -12, //!< No timer available
ERR_TIMER_ALREADY_RUNNING = -13, //!< Timer already running
ERR_TIMER_NOT_RUNNING = -14, //!< Timer not running
/**
* \brief Operation in progress
*
* This status code is for driver-internal use when an operation
* is currently being performed.
*
* \note Drivers should never return this status code to any
* callers. It is strictly for internal use.
*/
OPERATION_IN_PROGRESS = -128,
};
typedef enum status_code_wireless status_code_t;
/** @} */
#endif /* STATUS_CODES_H_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,260 @@
/**
* \file
*
* \brief Interface of the USB Device Controller (UDC)
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDC_H_
#define _UDC_H_
#include "conf_usb.h"
#include "usb_protocol.h"
#include "udc_desc.h"
#include "udd.h"
#if USB_DEVICE_VENDOR_ID == 0
# error USB_DEVICE_VENDOR_ID cannot be equal to 0
#endif
#if USB_DEVICE_PRODUCT_ID == 0
# error USB_DEVICE_PRODUCT_ID cannot be equal to 0
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* \ingroup usb_device_group
* \defgroup udc_group USB Device Controller (UDC)
*
* The UDC provides a high-level abstraction of the usb device.
* You can use these functions to control the main device state
* (start/attach/wakeup).
*
* \section USB_DEVICE_CONF USB Device Custom configuration
* The following USB Device configuration must be included in the conf_usb.h
* file of the application.
*
* USB_DEVICE_VENDOR_ID (Word)<br>
* Vendor ID provided by USB org (ATMEL 0x03EB).
*
* USB_DEVICE_PRODUCT_ID (Word)<br>
* Product ID (Referenced in usb_atmel.h).
*
* USB_DEVICE_MAJOR_VERSION (Byte)<br>
* Major version of the device
*
* USB_DEVICE_MINOR_VERSION (Byte)<br>
* Minor version of the device
*
* USB_DEVICE_MANUFACTURE_NAME (string)<br>
* ASCII name for the manufacture
*
* USB_DEVICE_PRODUCT_NAME (string)<br>
* ASCII name for the product
*
* USB_DEVICE_SERIAL_NAME (string)<br>
* ASCII name to enable and set a serial number
*
* USB_DEVICE_POWER (Numeric)<br>
* (unit mA) Maximum device power
*
* USB_DEVICE_ATTR (Byte)<br>
* USB attributes available:
* - USB_CONFIG_ATTR_SELF_POWERED
* - USB_CONFIG_ATTR_REMOTE_WAKEUP
* Note: if remote wake enabled then defines remotewakeup callbacks,
* see Table 5-2. External API from UDC - Callback
*
* USB_DEVICE_LOW_SPEED (Only defined)<br>
* Force the USB Device to run in low speed
*
* USB_DEVICE_HS_SUPPORT (Only defined)<br>
* Authorize the USB Device to run in high speed
*
* USB_DEVICE_MAX_EP (Byte)<br>
* Define the maximum endpoint number used by the USB Device.<br>
* This one is already defined in UDI default configuration.
* Ex:
* - When endpoint control 0x00, endpoint 0x01 and
* endpoint 0x82 is used then USB_DEVICE_MAX_EP=2
* - When only endpoint control 0x00 is used then USB_DEVICE_MAX_EP=0
* - When endpoint 0x01 and endpoint 0x81 is used then USB_DEVICE_MAX_EP=1<br>
* (configuration not possible on USBB interface)
* @{
*/
/**
* \brief Authorizes the VBUS event
*
* \return true, if the VBUS monitoring is possible.
*
* \section udc_vbus_monitoring VBus monitoring used cases
*
* The VBus monitoring is used only for USB SELF Power application.
*
* - By default the USB device is automatically attached when Vbus is high
* or when USB is start for devices without internal Vbus monitoring.
* conf_usb.h file does not contains define USB_DEVICE_ATTACH_AUTO_DISABLE.
* \code //#define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
*
* - Add custom VBUS monitoring. conf_usb.h file contains define
* USB_DEVICE_ATTACH_AUTO_DISABLE:
* \code #define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
* User C file contains:
* \code
// Authorize VBUS monitoring
if (!udc_include_vbus_monitoring()) {
// Implement custom VBUS monitoring via GPIO or other
}
Event_VBUS_present() // VBUS interrupt or GPIO interrupt or other
{
// Attach USB Device
udc_attach();
}
\endcode
*
* - Case of battery charging. conf_usb.h file contains define
* USB_DEVICE_ATTACH_AUTO_DISABLE:
* \code #define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
* User C file contains:
* \code
Event VBUS present() // VBUS interrupt or GPIO interrupt or ..
{
// Authorize battery charging, but wait key press to start USB.
}
Event Key press()
{
// Stop batteries charging
// Start USB
udc_attach();
}
\endcode
*/
static inline bool udc_include_vbus_monitoring(void)
{
return udd_include_vbus_monitoring();
}
/*! \brief Start the USB Device stack
*/
void udc_start(void);
/*! \brief Stop the USB Device stack
*/
void udc_stop(void);
/**
* \brief Attach device to the bus when possible
*
* \warning If a VBus control is included in driver,
* then it will attach device when an acceptable Vbus
* level from the host is detected.
*/
static inline void udc_attach(void)
{
udd_attach();
}
/**
* \brief Detaches the device from the bus
*
* The driver must remove pull-up on USB line D- or D+.
*/
static inline void udc_detach(void)
{
udd_detach();
}
/*! \brief The USB driver sends a resume signal called \e "Upstream Resume"
* This is authorized only when the remote wakeup feature is enabled by host.
*/
static inline void udc_remotewakeup(void)
{
udd_send_remotewakeup();
}
/**
* \brief Returns a pointer on the current interface descriptor
*
* \return pointer on the current interface descriptor.
*/
usb_iface_desc_t UDC_DESC_STORAGE *udc_get_interface_desc(void);
//@}
/**
* \ingroup usb_group
* \defgroup usb_device_group USB Stack Device
*
* This module includes USB Stack Device implementation.
* The stack is divided in three parts:
* - USB Device Controller (UDC) provides USB chapter 9 compliance
* - USB Device Interface (UDI) provides USB Class compliance
* - USB Device Driver (UDD) provides USB Driver for each Atmel MCU
* Many USB Device applications can be implemented on Atmel MCU.
* Atmel provides many application notes for different applications:
* - AVR4900, provides general information about Device Stack
* - AVR4901, explains how to create a new class
* - AVR4902, explains how to create a composite device
* - AVR49xx, all device classes provided in ASF have an application note
*
* A basic USB knowledge is required to understand the USB Device
* Class application notes (HID,MS,CDC,PHDC,...).
* Then, to create an USB device with
* only one class provided by ASF, refer directly to the application note
* corresponding to this USB class. The USB Device application note for
* New Class and Composite is dedicated to advanced USB users.
*
* @{
*/
//! @}
#ifdef __cplusplus
}
#endif
#endif // _UDC_H_

View File

@ -0,0 +1,135 @@
/**
* \file
*
* \brief Common API for USB Device Interface
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDC_DESC_H_
#define _UDC_DESC_H_
#include "conf_usb.h"
#include "usb_protocol.h"
#include "udi.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \ingroup udc_group
* \defgroup udc_desc_group USB Device Descriptor
*
* @{
*/
/**
* \brief Defines the memory's location of USB descriptors
*
* By default the Descriptor is stored in RAM
* (UDC_DESC_STORAGE is defined empty).
*
* If you have need to free RAM space,
* it is possible to put descriptor in flash in following case:
* - USB driver authorize flash transfer (USBB on UC3 and USB on Mega)
* - USB Device is not high speed (UDC no need to change USB descriptors)
*
* For UC3 application used "const".
*
* For Mega application used "code".
*/
#define UDC_DESC_STORAGE
// Descriptor storage in internal RAM
#if (defined UDC_DATA_USE_HRAM_SUPPORT)
#if defined(__GNUC__)
#define UDC_DATA(x) COMPILER_WORD_ALIGNED __attribute__((__section__(".data_hram0")))
#define UDC_BSS(x) COMPILER_ALIGNED(x) __attribute__((__section__(".bss_hram0")))
#elif defined(__ICCAVR32__)
#define UDC_DATA(x) COMPILER_ALIGNED(x) __data32
#define UDC_BSS(x) COMPILER_ALIGNED(x) __data32
#endif
#else
#define UDC_DATA(x) COMPILER_ALIGNED(x)
#define UDC_BSS(x) COMPILER_ALIGNED(x)
#endif
/**
* \brief Configuration descriptor and UDI link for one USB speed
*/
typedef struct {
//! USB configuration descriptor
usb_conf_desc_t UDC_DESC_STORAGE *desc;
//! Array of UDI API pointer
udi_api_t UDC_DESC_STORAGE *UDC_DESC_STORAGE * udi_apis;
} udc_config_speed_t;
/**
* \brief All information about the USB Device
*/
typedef struct {
//! USB device descriptor for low or full speed
usb_dev_desc_t UDC_DESC_STORAGE *confdev_lsfs;
//! USB configuration descriptor and UDI API pointers for low or full speed
udc_config_speed_t UDC_DESC_STORAGE *conf_lsfs;
#ifdef USB_DEVICE_HS_SUPPORT
//! USB device descriptor for high speed
usb_dev_desc_t UDC_DESC_STORAGE *confdev_hs;
//! USB device qualifier, only use in high speed mode
usb_dev_qual_desc_t UDC_DESC_STORAGE *qualifier;
//! USB configuration descriptor and UDI API pointers for high speed
udc_config_speed_t UDC_DESC_STORAGE *conf_hs;
#endif
usb_dev_bos_desc_t UDC_DESC_STORAGE *conf_bos;
} udc_config_t;
//! Global variables of USB Device Descriptor and UDI links
extern UDC_DESC_STORAGE udc_config_t udc_config;
//@}
#ifdef __cplusplus
}
#endif
#endif // _UDC_DESC_H_

View File

@ -0,0 +1,396 @@
/**
* \file
*
* \brief Common API for USB Device Drivers (UDD)
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDD_H_
#define _UDD_H_
#include "usb_protocol.h"
#include "udc_desc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \ingroup usb_device_group
* \defgroup udd_group USB Device Driver (UDD)
*
* The UDD driver provides a low-level abstraction of the device
* controller hardware. Most events coming from the hardware such as
* interrupts, which may cause the UDD to call into the UDC and UDI.
*
* @{
*/
//! \brief Endpoint identifier
typedef uint8_t udd_ep_id_t;
//! \brief Endpoint transfer status
//! Returned in parameters of callback register via udd_ep_run routine.
typedef enum {
UDD_EP_TRANSFER_OK = 0,
UDD_EP_TRANSFER_ABORT = 1,
} udd_ep_status_t;
/**
* \brief Global variable to give and record information of the setup request management
*
* This global variable allows to decode and response a setup request.
* It can be updated by udc_process_setup() from UDC or *setup() from UDIs.
*/
typedef struct {
//! Data received in USB SETUP packet
//! Note: The swap of "req.wValues" from uin16_t to le16_t is done by UDD.
usb_setup_req_t req;
//! Point to buffer to send or fill with data following SETUP packet
//! This buffer must be word align for DATA IN phase (use prefix COMPILER_WORD_ALIGNED for buffer)
uint8_t *payload;
//! Size of buffer to send or fill, and content the number of byte transfered
uint16_t payload_size;
//! Callback called after reception of ZLP from setup request
void (*callback) (void);
//! Callback called when the buffer given (.payload) is full or empty.
//! This one return false to abort data transfer, or true with a new buffer in .payload.
bool(*over_under_run) (void);
} udd_ctrl_request_t;
extern udd_ctrl_request_t udd_g_ctrlreq;
//! Return true if the setup request \a udd_g_ctrlreq indicates IN data transfer
#define Udd_setup_is_in() \
(USB_REQ_DIR_IN == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK))
//! Return true if the setup request \a udd_g_ctrlreq indicates OUT data transfer
#define Udd_setup_is_out() \
(USB_REQ_DIR_OUT == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK))
//! Return the type of the SETUP request \a udd_g_ctrlreq. \see usb_reqtype.
#define Udd_setup_type() \
(udd_g_ctrlreq.req.bmRequestType & USB_REQ_TYPE_MASK)
//! Return the recipient of the SETUP request \a udd_g_ctrlreq. \see usb_recipient
#define Udd_setup_recipient() \
(udd_g_ctrlreq.req.bmRequestType & USB_REQ_RECIP_MASK)
/**
* \brief End of halt callback function type.
* Registered by routine udd_ep_wait_stall_clear()
* Callback called when endpoint stall is cleared.
*/
typedef void (*udd_callback_halt_cleared_t) (void);
/**
* \brief End of transfer callback function type.
* Registered by routine udd_ep_run()
* Callback called by USB interrupt after data transfer or abort (reset,...).
*
* \param status UDD_EP_TRANSFER_OK, if transfer is complete
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
* \param n number of data transfered
*/
typedef void (*udd_callback_trans_t) (udd_ep_status_t status,
iram_size_t nb_transfered, udd_ep_id_t ep);
/**
* \brief Authorizes the VBUS event
*
* \return true, if the VBUS monitoring is possible.
*/
bool udd_include_vbus_monitoring(void);
/**
* \brief Enables the USB Device mode
*/
void udd_enable(void);
/**
* \brief Disables the USB Device mode
*/
void udd_disable(void);
/**
* \brief Attach device to the bus when possible
*
* \warning If a VBus control is included in driver,
* then it will attach device when an acceptable Vbus
* level from the host is detected.
*/
void udd_attach(void);
/**
* \brief Detaches the device from the bus
*
* The driver must remove pull-up on USB line D- or D+.
*/
void udd_detach(void);
/**
* \brief Test whether the USB Device Controller is running at high
* speed or not.
*
* \return \c true if the Device is running at high speed mode, otherwise \c false.
*/
bool udd_is_high_speed(void);
/**
* \brief Changes the USB address of device
*
* \param address New USB address
*/
void udd_set_address(uint8_t address);
/**
* \brief Returns the USB address of device
*
* \return USB address
*/
uint8_t udd_getaddress(void);
/**
* \brief Returns the current start of frame number
*
* \return current start of frame number.
*/
uint16_t udd_get_frame_number(void);
/**
* \brief Returns the current micro start of frame number
*
* \return current micro start of frame number required in high speed mode.
*/
uint16_t udd_get_micro_frame_number(void);
/*! \brief The USB driver sends a resume signal called Upstream Resume
*/
void udd_send_remotewakeup(void);
/**
* \brief Load setup payload
*
* \param payload Pointer on payload
* \param payload_size Size of payload
*/
void udd_set_setup_payload( uint8_t *payload, uint16_t payload_size );
/**
* \name Endpoint Management
*
* The following functions allow drivers to create and remove
* endpoints, as well as set, clear and query their "halted" and
* "wedged" states.
*/
//@{
#if (USB_DEVICE_MAX_EP != 0)
/**
* \brief Configures and enables an endpoint
*
* \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT).
* \param bmAttributes Attributes of endpoint declared in the descriptor.
* \param MaxEndpointSize Endpoint maximum size
*
* \return \c 1 if the endpoint is enabled, otherwise \c 0.
*/
bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes,
uint16_t MaxEndpointSize);
/**
* \brief Disables an endpoint
*
* \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT).
*/
void udd_ep_free(udd_ep_id_t ep);
/**
* \brief Check if the endpoint \a ep is halted.
*
* \param ep The ID of the endpoint to check.
*
* \return \c 1 if \a ep is halted, otherwise \c 0.
*/
bool udd_ep_is_halted(udd_ep_id_t ep);
/**
* \brief Set the halted state of the endpoint \a ep
*
* After calling this function, any transaction on \a ep will result
* in a STALL handshake being sent. Any pending transactions will be
* performed first, however.
*
* \param ep The ID of the endpoint to be halted
*
* \return \c 1 if \a ep is halted, otherwise \c 0.
*/
bool udd_ep_set_halt(udd_ep_id_t ep);
/**
* \brief Clear the halted state of the endpoint \a ep
*
* After calling this function, any transaction on \a ep will
* be handled normally, i.e. a STALL handshake will not be sent, and
* the data toggle sequence will start at DATA0.
*
* \param ep The ID of the endpoint to be un-halted
*
* \return \c 1 if function was successfully done, otherwise \c 0.
*/
bool udd_ep_clear_halt(udd_ep_id_t ep);
/**
* \brief Registers a callback to call when endpoint halt is cleared
*
* \param ep The ID of the endpoint to use
* \param callback NULL or function to call when endpoint halt is cleared
*
* \warning if the endpoint is not halted then the \a callback is called immediately.
*
* \return \c 1 if the register is accepted, otherwise \c 0.
*/
bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
udd_callback_halt_cleared_t callback);
/**
* \brief Allows to receive or send data on an endpoint
*
* The driver uses a specific DMA USB to transfer data
* from internal RAM to endpoint, if this one is available.
* When the transfer is finished or aborted (stall, reset, ...), the \a callback is called.
* The \a callback returns the transfer status and eventually the number of byte transfered.
* Note: The control endpoint is not authorized.
*
* \param ep The ID of the endpoint to use
* \param b_shortpacket Enabled automatic short packet
* \param buf Buffer on Internal RAM to send or fill.
* It must be align, then use COMPILER_WORD_ALIGNED.
* \param buf_size Buffer size to send or fill
* \param callback NULL or function to call at the end of transfer
*
* \warning About \a b_shortpacket, for IN endpoint it means that a short packet
* (or a Zero Length Packet) will be sent to the USB line to properly close the usb
* transfer at the end of the data transfer.
* For Bulk and Interrupt OUT endpoint, it will automatically stop the transfer
* at the end of the data transfer (received short packet).
*
* \return \c 1 if function was successfully done, otherwise \c 0.
*/
bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket,
uint8_t *buf, iram_size_t buf_size,
udd_callback_trans_t callback);
/**
* \brief Aborts transfer on going on endpoint
*
* If a transfer is on going, then it is stopped and
* the callback registered is called to signal the end of transfer.
* Note: The control endpoint is not authorized.
*
* \param ep Endpoint to abort
*/
void udd_ep_abort(udd_ep_id_t ep);
#endif
//@}
/**
* \name High speed test mode management
*
* The following functions allow the device to jump to a specific test mode required in high speed mode.
*/
//@{
void udd_test_mode_j(void);
void udd_test_mode_k(void);
void udd_test_mode_se0_nak(void);
void udd_test_mode_packet(void);
//@}
/**
* \name UDC callbacks to provide for UDD
*
* The following callbacks are used by UDD.
*/
//@{
/**
* \brief Decodes and manages a setup request
*
* The driver call it when a SETUP packet is received.
* The \c udd_g_ctrlreq contains the data of SETUP packet.
* If this callback accepts the setup request then it must
* return \c 1 and eventually update \c udd_g_ctrlreq to send or receive data.
*
* \return \c 1 if the request is accepted, otherwise \c 0.
*/
extern bool udc_process_setup(void);
/**
* \brief Reset the UDC
*
* The UDC must reset all configuration.
*/
extern void udc_reset(void);
/**
* \brief To signal that a SOF is occurred
*
* The UDC must send the signal to all UDIs enabled
*/
extern void udc_sof_notify(void);
//@}
//@}
#ifdef __cplusplus
}
#endif
#endif // _UDD_H_

View File

@ -0,0 +1,133 @@
/**
* \file
*
* \brief Common API for USB Device Interface
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDI_H_
#define _UDI_H_
#include "conf_usb.h"
#include "usb_protocol.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \ingroup usb_device_group
* \defgroup udi_group USB Device Interface (UDI)
* The UDI provides a common API for all classes,
* and this is used by UDC for the main control of USB Device interface.
* @{
*/
/**
* \brief UDI API.
*
* The callbacks within this structure are called only by
* USB Device Controller (UDC)
*
* The udc_get_interface_desc() can be use by UDI to know the interface descriptor
* selected by UDC.
*/
typedef struct {
/**
* \brief Enable the interface.
*
* This function is called when the host selects a configuration
* to which this interface belongs through a Set Configuration
* request, and when the host selects an alternate setting of
* this interface through a Set Interface request.
*
* \return \c 1 if function was successfully done, otherwise \c 0.
*/
bool(*enable) (void);
/**
* \brief Disable the interface.
*
* This function is called when this interface is currently
* active, and
* - the host selects any configuration through a Set
* Configuration request, or
* - the host issues a USB reset, or
* - the device is detached from the host (i.e. Vbus is no
* longer present)
*/
void (*disable) (void);
/**
* \brief Handle a control request directed at an interface.
*
* This function is called when this interface is currently
* active and the host sends a SETUP request
* with this interface as the recipient.
*
* Use udd_g_ctrlreq to decode and response to SETUP request.
*
* \return \c 1 if this interface supports the SETUP request, otherwise \c 0.
*/
bool(*setup) (void);
/**
* \brief Returns the current setting of the selected interface.
*
* This function is called when UDC when know alternate setting of selected interface.
*
* \return alternate setting of selected interface
*/
uint8_t(*getsetting) (void);
/**
* \brief To signal that a SOF is occurred
*/
void(*sof_notify) (void);
} udi_api_t;
//@}
#ifdef __cplusplus
}
#endif
#endif // _UDI_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,381 @@
/**
* \file
*
* \brief USB Device Communication Device Class (CDC) interface definitions.
*
* Copyright (c) 2009-2016 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDI_CDC_H_
#define _UDI_CDC_H_
#ifdef CDC
#include "conf_usb.h"
#include "usb_protocol.h"
#include "usb_protocol_cdc.h"
#include "udd.h"
#include "udc_desc.h"
#include "udi.h"
// Check the number of port
#ifndef UDI_CDC_PORT_NB
# define UDI_CDC_PORT_NB 1
#endif
#if (UDI_CDC_PORT_NB > 1)
# error UDI_CDC_PORT_NB must be at most 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup udi_cdc_group_udc
* @{
*/
//! Global structure which contains standard UDI API for UDC
extern UDC_DESC_STORAGE udi_api_t udi_api_cdc_comm;
extern UDC_DESC_STORAGE udi_api_t udi_api_cdc_data;
//@}
//#define CDC_ACM_SIZE 64 see usb_protocol_cdc.h
//#define CDC_RX_SIZE 64
//! CDC communication endpoints size for all speeds
#define UDI_CDC_COMM_EP_SIZE CDC_ACM_SIZE
//! CDC data endpoints size for FS speed (8B, 16B, 32B, 64B)
#define UDI_CDC_DATA_EPS_FS_SIZE CDC_RX_SIZE
#define CDC_PRINT_BUF_SIZE 256
extern char printbuf[CDC_PRINT_BUF_SIZE];
//@}
/**
* \ingroup udi_group
* \defgroup udi_cdc_group USB Device Interface (UDI) for Communication Class Device (CDC)
*
* Common APIs used by high level application to use this USB class.
*
* These routines are used to transfer and control data
* to/from USB CDC endpoint.
*
* See \ref udi_cdc_quickstart.
* @{
*/
/**
* \name Interface for application with single CDC interface support
*/
//@{
/**
* \brief Notify a state change of DCD signal
*
* \param b_set DCD is enabled if true, else disabled
*/
void udi_cdc_ctrl_signal_dcd(bool b_set);
/**
* \brief Notify a state change of DSR signal
*
* \param b_set DSR is enabled if true, else disabled
*/
void udi_cdc_ctrl_signal_dsr(bool b_set);
/**
* \brief Notify a framing error
*/
void udi_cdc_signal_framing_error(void);
/**
* \brief Notify a parity error
*/
void udi_cdc_signal_parity_error(void);
/**
* \brief Notify a overrun
*/
void udi_cdc_signal_overrun(void);
/**
* \brief Gets the number of byte received
*
* \return the number of data available
*/
iram_size_t udi_cdc_get_nb_received_data(void);
/**
* \brief This function checks if a character has been received on the CDC line
*
* \return \c 1 if a byte is ready to be read.
*/
bool udi_cdc_is_rx_ready(void);
/**
* \brief Waits and gets a value on CDC line
*
* \return value read on CDC line
*/
int udi_cdc_getc(void);
/**
* \brief Reads a RAM buffer on CDC line
*
* \param buf Values read
* \param size Number of value read
*
* \return the number of data remaining
*/
iram_size_t udi_cdc_read_buf(void* buf, iram_size_t size);
/**
* \brief Non polling reads of a up to 'size' data from CDC line
*
* \param port Communication port number to manage
* \param buf Buffer where to store read data
* \param size Maximum number of data to read (size of buffer)
*
* \return the number of data effectively read
*/
iram_size_t udi_cdc_read_no_polling(void* buf, iram_size_t size);
/**
* \brief Gets the number of free byte in TX buffer
*
* \return the number of free byte in TX buffer
*/
iram_size_t udi_cdc_get_free_tx_buffer(void);
/**
* \brief This function checks if a new character sent is possible
* The type int is used to support scanf redirection from compiler LIB.
*
* \return \c 1 if a new character can be sent
*/
bool udi_cdc_is_tx_ready(void);
/**
* \brief Puts a byte on CDC line
* The type int is used to support printf redirection from compiler LIB.
*
* \param value Value to put
*
* \return \c 1 if function was successfully done, otherwise \c 0.
*/
int udi_cdc_putc(int value);
/**
* \brief Writes a RAM buffer on CDC line
*
* \param buf Values to write
* \param size Number of value to write
*
* \return the number of data remaining
*/
iram_size_t udi_cdc_write_buf(const void* buf, iram_size_t size);
//@}
/**
* \name Interface for application with multi CDC interfaces support
*/
//@{
/**
* \brief Notify a state change of DCD signal
*
* \param port Communication port number to manage
* \param b_set DCD is enabled if true, else disabled
*/
void udi_cdc_multi_ctrl_signal_dcd(uint8_t port, bool b_set);
/**
* \brief Notify a state change of DSR signal
*
* \param port Communication port number to manage
* \param b_set DSR is enabled if true, else disabled
*/
void udi_cdc_multi_ctrl_signal_dsr(uint8_t port, bool b_set);
/**
* \brief Notify a framing error
*
* \param port Communication port number to manage
*/
void udi_cdc_multi_signal_framing_error(uint8_t port);
/**
* \brief Notify a parity error
*
* \param port Communication port number to manage
*/
void udi_cdc_multi_signal_parity_error(uint8_t port);
/**
* \brief Notify a overrun
*
* \param port Communication port number to manage
*/
void udi_cdc_multi_signal_overrun(uint8_t port);
/**
* \brief Gets the number of byte received
*
* \param port Communication port number to manage
*
* \return the number of data available
*/
iram_size_t udi_cdc_multi_get_nb_received_data(uint8_t port);
/**
* \brief This function checks if a character has been received on the CDC line
*
* \param port Communication port number to manage
*
* \return \c 1 if a byte is ready to be read.
*/
bool udi_cdc_multi_is_rx_ready(uint8_t port);
/**
* \brief Waits and gets a value on CDC line
*
* \param port Communication port number to manage
*
* \return value read on CDC line
*/
int udi_cdc_multi_getc(uint8_t port);
/**
* \brief Reads a RAM buffer on CDC line
*
* \param port Communication port number to manage
* \param buf Values read
* \param size Number of values read
*
* \return the number of data remaining
*/
iram_size_t udi_cdc_multi_read_buf(uint8_t port, void* buf, iram_size_t size);
/**
* \brief Gets the number of free byte in TX buffer
*
* \param port Communication port number to manage
*
* \return the number of free byte in TX buffer
*/
iram_size_t udi_cdc_multi_get_free_tx_buffer(uint8_t port);
/**
* \brief This function checks if a new character sent is possible
* The type int is used to support scanf redirection from compiler LIB.
*
* \param port Communication port number to manage
*
* \return \c 1 if a new character can be sent
*/
bool udi_cdc_multi_is_tx_ready(uint8_t port);
/**
* \brief Puts a byte on CDC line
* The type int is used to support printf redirection from compiler LIB.
*
* \param port Communication port number to manage
* \param value Value to put
*
* \return \c 1 if function was successfully done, otherwise \c 0.
*/
int udi_cdc_multi_putc(uint8_t port, int value);
/**
* \brief Writes a RAM buffer on CDC line
*
* \param port Communication port number to manage
* \param buf Values to write
* \param size Number of value to write
*
* \return the number of data remaining
*/
iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t size);
//@}
#define CDC_PRINTBUF_SIZE 256
extern char printbuf[CDC_PRINTBUF_SIZE];
#define CDC_INBUF_SIZE 256
typedef struct {
uint32_t count;
uint32_t lastcount;
char buf[CDC_INBUF_SIZE];
} inbuf_t;
#else //CDC
// keep these to accommodate calls if remaining
#define CDC_PRINTBUF_SIZE 1
extern char printbuf[CDC_PRINTBUF_SIZE];
#define CDC_INBUF_SIZE 1
typedef struct {
uint32_t count;
uint32_t lastcount;
char buf[CDC_INBUF_SIZE];
} inbuf_t;
extern inbuf_t inbuf;
#endif //CDC
uint32_t CDC_print(char *printbuf);
uint32_t CDC_input(void);
void CDC_init(void);
#define __xprintf dpf
int dpf(const char *_Format, ...);
#ifdef __cplusplus
}
#endif
#endif // _UDI_CDC_H_

View File

@ -0,0 +1,72 @@
/**
* \file
*
* \brief Default CDC configuration for a USB Device with a single interface
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDI_CDC_CONF_H_
#define _UDI_CDC_CONF_H_
#include "usb_protocol_cdc.h"
#include "conf_usb.h"
#include "udi_device_conf.h"
#ifndef UDI_CDC_PORT_NB
#define UDI_CDC_PORT_NB 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define UDI_CDC_DATA_EP_IN_0 ((CDC_TX_ENDPOINT) | (USB_EP_DIR_IN)) //TX
#define UDI_CDC_DATA_EP_OUT_0 ((CDC_RX_ENDPOINT) | (USB_EP_DIR_OUT)) // RX
#define UDI_CDC_COMM_EP_0 ((CDC_ACM_ENDPOINT) | (USB_EP_DIR_IN)) // Notify endpoint
#define UDI_CDC_COMM_IFACE_NUMBER_0 (CDC_STATUS_INTERFACE)
#define UDI_CDC_DATA_IFACE_NUMBER_0 (CDC_DATA_INTERFACE)
#ifdef __cplusplus
}
#endif
#endif // _UDI_CDC_CONF_H_

View File

@ -0,0 +1,715 @@
/*
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/>.
*/
#ifndef _UDI_DEVICE_CONF_H_
#define _UDI_DEVICE_CONF_H_
#include "udi_device_epsize.h"
#include "usb_protocol.h"
#include "compiler.h"
#include "usb_protocol_hid.h"
#define DEVICE_CLASS 0
#define DEVICE_SUBCLASS 0
#define DEVICE_PROTOCOL 0
#define KBD
//#define MOUSE_ENABLE //rules.mk
#ifdef MOUSE_ENABLE
#define MOU
#endif
//#define EXTRAKEY_ENABLE //rules.mk
#ifdef EXTRAKEY_ENABLE
#define EXK
#endif
//#define RAW_ENABLE //rules.mk
#ifdef RAW_ENABLE
#define RAW
#endif
//#define CONSOLE_ENABLE //deferred implementation
//#ifdef CONSOLE_ENABLE
//#define CON
//#endif
//#define NKRO_ENABLE //rules.mk
#ifdef NKRO_ENABLE
#define NKRO
#endif
//#define MIDI_ENABLE //deferred implementation
//#ifdef MIDI_ENABLE
//#define MIDI
//#endif
//#define VIRTSER_ENABLE //rules.mk
#ifdef VIRTSER_ENABLE
#define CDC
//because CDC uses IAD (interface association descriptor
//per USB Interface Association Descriptor Device Class Code and Use Model 7/23/2003 Rev 1.0)
#undef DEVICE_CLASS
#define DEVICE_CLASS 0xEF
#undef DEVICE_SUBCLASS
#define DEVICE_SUBCLASS 0x02
#undef DEVICE_PROTOCOL
#define DEVICE_PROTOCOL 0x01
#endif
/* number of interfaces */
#define NEXT_INTERFACE_0 0
#ifdef KBD
#define KEYBOARD_INTERFACE NEXT_INTERFACE_0
#define NEXT_INTERFACE_1 (KEYBOARD_INTERFACE + 1)
#define UDI_HID_KBD_IFACE_NUMBER KEYBOARD_INTERFACE
#else
#define NEXT_INTERFACE_1 NEXT_INTERFACE_0
#endif
// It is important that the Raw HID interface is at a constant
// interface number, to support Linux/OSX platforms and chrome.hid
// If Raw HID is enabled, let it be always 1.
#ifdef RAW
#define RAW_INTERFACE NEXT_INTERFACE_1
#define NEXT_INTERFACE_2 (RAW_INTERFACE + 1)
#else
#define NEXT_INTERFACE_2 NEXT_INTERFACE_1
#endif
#ifdef MOU
#define MOUSE_INTERFACE NEXT_INTERFACE_2
#define UDI_HID_MOU_IFACE_NUMBER MOUSE_INTERFACE
#define NEXT_INTERFACE_3 (MOUSE_INTERFACE + 1)
#else
#define NEXT_INTERFACE_3 NEXT_INTERFACE_2
#endif
#ifdef EXK
#define EXTRAKEY_INTERFACE NEXT_INTERFACE_3
#define NEXT_INTERFACE_4 (EXTRAKEY_INTERFACE + 1)
#define UDI_HID_EXK_IFACE_NUMBER EXTRAKEY_INTERFACE
#else
#define NEXT_INTERFACE_4 NEXT_INTERFACE_3
#endif
#ifdef CON
#define CONSOLE_INTERFACE NEXT_INTERFACE_4
#define NEXT_INTERFACE_5 (CONSOLE_INTERFACE + 1)
#else
#define NEXT_INTERFACE_5 NEXT_INTERFACE_4
#endif
#ifdef NKRO
#define NKRO_INTERFACE NEXT_INTERFACE_5
#define NEXT_INTERFACE_6 (NKRO_INTERFACE + 1)
#define UDI_HID_NKRO_IFACE_NUMBER NKRO_INTERFACE
#else
#define NEXT_INTERFACE_6 NEXT_INTERFACE_5
#endif
#ifdef MIDI
#define AC_INTERFACE NEXT_INTERFACE_6
#define AS_INTERFACE (AC_INTERFACE + 1)
#define NEXT_INTERFACE_7 (AS_INTERFACE + 1)
#else
#define NEXT_INTERFACE_7 NEXT_INTERFACE_6
#endif
#ifdef CDC
#define CCI_INTERFACE NEXT_INTERFACE_7
#define CDI_INTERFACE (CCI_INTERFACE + 1)
#define NEXT_INTERFACE_8 (CDI_INTERFACE + 1)
#define CDC_STATUS_INTERFACE CCI_INTERFACE
#define CDC_DATA_INTERFACE CDI_INTERFACE
#else
#define NEXT_INTERFACE_8 NEXT_INTERFACE_7
#endif
/* nubmer of interfaces */
#define TOTAL_INTERFACES NEXT_INTERFACE_8
#define USB_DEVICE_NB_INTERFACE TOTAL_INTERFACES
// **********************************************************************
// Endopoint number and size
// **********************************************************************
#define USB_DEVICE_EP_CTRL_SIZE 8
#define NEXT_IN_EPNUM_0 1
#define NEXT_OUT_EPNUM_0 1
#ifdef KBD
#define KEYBOARD_IN_EPNUM NEXT_IN_EPNUM_0
#define UDI_HID_KBD_EP_IN KEYBOARD_IN_EPNUM
#define NEXT_IN_EPNUM_1 (KEYBOARD_IN_EPNUM + 1)
#define UDI_HID_KBD_EP_SIZE KEYBOARD_EPSIZE
#define KBD_POLLING_INTERVAL 10
#ifndef UDI_HID_KBD_STRING_ID
#define UDI_HID_KBD_STRING_ID 0
#endif
#else
#define NEXT_IN_EPNUM_1 NEXT_IN_EPNUM_0
#endif
#ifdef MOU
#define MOUSE_IN_EPNUM NEXT_IN_EPNUM_1
#define NEXT_IN_EPNUM_2 (MOUSE_IN_EPNUM + 1)
#define UDI_HID_MOU_EP_IN MOUSE_IN_EPNUM
#define UDI_HID_MOU_EP_SIZE MOUSE_EPSIZE
#define MOU_POLLING_INTERVAL 10
#ifndef UDI_HID_MOU_STRING_ID
#define UDI_HID_MOU_STRING_ID 0
#endif
#else
#define NEXT_IN_EPNUM_2 NEXT_IN_EPNUM_1
#endif
#ifdef EXK
#define EXTRAKEY_IN_EPNUM NEXT_IN_EPNUM_2
#define UDI_HID_EXK_EP_IN EXTRAKEY_IN_EPNUM
#define NEXT_IN_EPNUM_3 (EXTRAKEY_IN_EPNUM + 1)
#define UDI_HID_EXK_EP_SIZE EXTRAKEY_EPSIZE
#define EXTRAKEY_POLLING_INTERVAL 10
#ifndef UDI_HID_EXK_STRING_ID
#define UDI_HID_EXK_STRING_ID 0
#endif
#else
#define NEXT_IN_EPNUM_3 NEXT_IN_EPNUM_2
#endif
#ifdef RAW
#define RAW_IN_EPNUM NEXT_IN_EPNUM_3
#define UDI_HID_RAW_EP_IN RAW_IN_EPNUM
#define NEXT_IN_EPNUM_4 (RAW_IN_EPNUM + 1)
#define RAW_OUT_EPNUM NEXT_OUT_EPNUM_0
#define UDI_HID_RAW_EP_OUT RAW_OUT_EPNUM
#define NEXT_OUT_EPNUM_1 (RAW_OUT_EPNUM + 1)
#define RAW_POLLING_INTERVAL 1
#ifndef UDI_HID_RAW_STRING_ID
#define UDI_HID_RAW_STRING_ID 0
#endif
#else
#define NEXT_IN_EPNUM_4 NEXT_IN_EPNUM_3
#define NEXT_OUT_EPNUM_1 NEXT_OUT_EPNUM_0
#endif
#ifdef CON
#define CONSOLE_IN_EPNUM NEXT_IN_EPNUM_4
#define NEXT_IN_EPNUM_5 (CONSOLE_IN_EPNUM + 1)
#define CONSOLE_OUT_EPNUM NEXT_OUT_EPNUM_1
#define NEXT_OUT_EPNUM_2 (CONSOLE_OUT_EPNUM + 1)
#define CONSOLE_POLLING_INTERVAL 1
#else
#define NEXT_IN_EPNUM_5 NEXT_IN_EPNUM_4
#define NEXT_OUT_EPNUM_2 NEXT_OUT_EPNUM_1
#endif
#ifdef NKRO
#define NKRO_IN_EPNUM NEXT_IN_EPNUM_5
#define UDI_HID_NKRO_EP_IN NKRO_IN_EPNUM
#define NEXT_IN_EPNUM_6 (NKRO_IN_EPNUM + 1)
#define UDI_HID_NKRO_EP_SIZE NKRO_EPSIZE
#define NKRO_POLLING_INTERVAL 1
#ifndef UDI_HID_NKRO_STRING_ID
#define UDI_HID_NKRO_STRING_ID 0
#endif
#else
#define NEXT_IN_EPNUM_6 NEXT_IN_EPNUM_5
#endif
#ifdef MIDI
#define MIDI_STREAM_IN_EPNUM NEXT_IN_EPNUM_6
#define NEXT_IN_EPNUM_7 (MIDI_STREAM_IN_EPNUM + 1)
#define MIDI_STREAM_OUT_EPNUM NEXT_OUT_EPNUM_2
#define NEXT_OUT_EPNUM_3 (MIDI_STREAM_OUT_EPNUM + 1)
#define MIDI_POLLING_INTERVAL 5
#else
#define NEXT_IN_EPNUM_7 NEXT_IN_EPNUM_6
#define NEXT_OUT_EPNUM_3 NEXT_OUT_EPNUM_2
#endif
#ifdef CDC
#define CDC_NOTIFICATION_EPNUM NEXT_IN_EPNUM_7
#define CDC_ACM_ENDPOINT CDC_NOTIFICATION_EPNUM
#define CDC_TX_ENDPOINT (CDC_NOTIFICATION_EPNUM + 1)
#define NEXT_IN_EPNUM_8 (CDC_TX_ENDPOINT + 1)
#define CDC_OUT_EPNUM NEXT_OUT_EPNUM_3
#define CDC_RX_ENDPOINT CDC_OUT_EPNUM
#define NEXT_OUT_EPNUM_4 (CDC_OUT_EPNUM + 1)
#define CDC_ACM_SIZE CDC_NOTIFICATION_EPSIZE
#define CDC_RX_SIZE CDC_EPSIZE //KFSMOD was 64
#define CDC_TX_SIZE CDC_RX_SIZE
#define CDC_ACM_POLLING_INTERVAL 255
#define CDC_EP_INTERVAL_STATUS CDC_ACM_POLLING_INTERVAL
#define CDC_DATA_POLLING_INTERVAL 5
#define CDC_EP_INTERVAL_DATA CDC_DATA_POLLING_INTERVAL
#define CDC_STATUS_NAME L"Virtual Serial Port - Status"
#define CDC_DATA_NAME L"Virtual Serial Port - Data"
#else
#define NEXT_IN_EPNUM_8 NEXT_IN_EPNUM_7
#define NEXT_OUT_EPNUM_4 NEXT_OUT_EPNUM_3
#endif
#define TOTAL_OUT_EP NEXT_OUT_EPNUM_4
#define TOTAL_IN_EP NEXT_IN_EPNUM_8
#define USB_DEVICE_MAX_EP (max(NEXT_OUT_EPNUM_4, NEXT_IN_EPNUM_8))
#if USB_DEVICE_MAX_EP > 8
#error "There are not enough available endpoints to support all functions. Remove some in the rules.mk file.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, VIRTSER)"
#endif
// **********************************************************************
// KBD Descriptor structure and content
// **********************************************************************
#ifdef KBD
COMPILER_PACK_SET(1)
typedef struct {
usb_iface_desc_t iface;
usb_hid_descriptor_t hid;
usb_ep_desc_t ep;
} udi_hid_kbd_desc_t;
typedef struct {
uint8_t array[59];
} udi_hid_kbd_report_desc_t;
#define UDI_HID_KBD_DESC {\
.iface.bLength = sizeof(usb_iface_desc_t),\
.iface.bDescriptorType = USB_DT_INTERFACE,\
.iface.bInterfaceNumber = UDI_HID_KBD_IFACE_NUMBER,\
.iface.bAlternateSetting = 0,\
.iface.bNumEndpoints = 1,\
.iface.bInterfaceClass = HID_CLASS,\
.iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
.iface.bInterfaceProtocol = HID_PROTOCOL_KEYBOARD,\
.iface.iInterface = UDI_HID_KBD_STRING_ID,\
.hid.bLength = sizeof(usb_hid_descriptor_t),\
.hid.bDescriptorType = USB_DT_HID,\
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
.hid.wDescriptorLength = LE16(sizeof(udi_hid_kbd_report_desc_t)),\
.ep.bLength = sizeof(usb_ep_desc_t),\
.ep.bDescriptorType = USB_DT_ENDPOINT,\
.ep.bEndpointAddress = UDI_HID_KBD_EP_IN | USB_EP_DIR_IN,\
.ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep.wMaxPacketSize = LE16(UDI_HID_KBD_EP_SIZE),\
.ep.bInterval = KBD_POLLING_INTERVAL,\
}
//set report buffer (from host)
extern uint8_t udi_hid_kbd_report_set;
//report buffer (to host)
#define UDI_HID_KBD_REPORT_SIZE 8
extern uint8_t udi_hid_kbd_report[UDI_HID_KBD_REPORT_SIZE];
COMPILER_PACK_RESET()
#endif //KBD
// **********************************************************************
// EXK Descriptor structure and content
// **********************************************************************
#ifdef EXK
COMPILER_PACK_SET(1)
typedef struct {
usb_iface_desc_t iface;
usb_hid_descriptor_t hid;
usb_ep_desc_t ep;
} udi_hid_exk_desc_t;
typedef struct {
uint8_t array[54];
} udi_hid_exk_report_desc_t;
#define UDI_HID_EXK_DESC {\
.iface.bLength = sizeof(usb_iface_desc_t),\
.iface.bDescriptorType = USB_DT_INTERFACE,\
.iface.bInterfaceNumber = UDI_HID_EXK_IFACE_NUMBER,\
.iface.bAlternateSetting = 0,\
.iface.bNumEndpoints = 1,\
.iface.bInterfaceClass = HID_CLASS,\
.iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
.iface.bInterfaceProtocol = HID_PROTOCOL_GENERIC,\
.iface.iInterface = UDI_HID_EXK_STRING_ID,\
.hid.bLength = sizeof(usb_hid_descriptor_t),\
.hid.bDescriptorType = USB_DT_HID,\
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
.hid.wDescriptorLength = LE16(sizeof(udi_hid_exk_report_desc_t)),\
.ep.bLength = sizeof(usb_ep_desc_t),\
.ep.bDescriptorType = USB_DT_ENDPOINT,\
.ep.bEndpointAddress = UDI_HID_EXK_EP_IN | USB_EP_DIR_IN,\
.ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep.wMaxPacketSize = LE16(UDI_HID_EXK_EP_SIZE),\
.ep.bInterval = EXTRAKEY_POLLING_INTERVAL,\
}
//set report buffer (from host)
extern uint8_t udi_hid_exk_report_set;
//report buffer
#define UDI_HID_EXK_REPORT_SIZE 3
typedef union {
struct {
uint8_t report_id;
uint16_t report_data;
} desc;
uint8_t raw[UDI_HID_EXK_REPORT_SIZE];
} udi_hid_exk_report_t;
extern udi_hid_exk_report_t udi_hid_exk_report;
COMPILER_PACK_RESET()
#endif //EXK
// **********************************************************************
// NKRO Descriptor structure and content
// **********************************************************************
#ifdef NKRO
COMPILER_PACK_SET(1)
typedef struct {
usb_iface_desc_t iface;
usb_hid_descriptor_t hid;
usb_ep_desc_t ep;
} udi_hid_nkro_desc_t;
typedef struct {
uint8_t array[57];
} udi_hid_nkro_report_desc_t;
#define UDI_HID_NKRO_DESC {\
.iface.bLength = sizeof(usb_iface_desc_t),\
.iface.bDescriptorType = USB_DT_INTERFACE,\
.iface.bInterfaceNumber = UDI_HID_NKRO_IFACE_NUMBER,\
.iface.bAlternateSetting = 0,\
.iface.bNumEndpoints = 1,\
.iface.bInterfaceClass = HID_CLASS,\
.iface.bInterfaceSubClass = HID_SUB_CLASS_NOBOOT,\
.iface.bInterfaceProtocol = HID_PROTOCOL_KEYBOARD,\
.iface.iInterface = UDI_HID_NKRO_STRING_ID,\
.hid.bLength = sizeof(usb_hid_descriptor_t),\
.hid.bDescriptorType = USB_DT_HID,\
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
.hid.wDescriptorLength = LE16(sizeof(udi_hid_nkro_report_desc_t)),\
.ep.bLength = sizeof(usb_ep_desc_t),\
.ep.bDescriptorType = USB_DT_ENDPOINT,\
.ep.bEndpointAddress = UDI_HID_NKRO_EP_IN | USB_EP_DIR_IN,\
.ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep.wMaxPacketSize = LE16(UDI_HID_NKRO_EP_SIZE),\
.ep.bInterval = NKRO_POLLING_INTERVAL,\
}
//set report buffer
extern uint8_t udi_hid_nkro_report_set;
//report buffer
#define UDI_HID_NKRO_REPORT_SIZE 32
extern uint8_t udi_hid_nkro_report[UDI_HID_NKRO_REPORT_SIZE];
COMPILER_PACK_RESET()
#endif //NKRO
// **********************************************************************
// MOU Descriptor structure and content
// **********************************************************************
#ifdef MOU
COMPILER_PACK_SET(1)
typedef struct {
usb_iface_desc_t iface;
usb_hid_descriptor_t hid;
usb_ep_desc_t ep;
} udi_hid_mou_desc_t;
typedef struct {
uint8_t array[77];//MOU PDS
} udi_hid_mou_report_desc_t;
#define UDI_HID_MOU_DESC {\
.iface.bLength = sizeof(usb_iface_desc_t),\
.iface.bDescriptorType = USB_DT_INTERFACE,\
.iface.bInterfaceNumber = MOUSE_INTERFACE,\
.iface.bAlternateSetting = 0,\
.iface.bNumEndpoints = 1,\
.iface.bInterfaceClass = HID_CLASS,\
.iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
.iface.bInterfaceProtocol = HID_PROTOCOL_MOUSE,\
.iface.iInterface = UDI_HID_MOU_STRING_ID,\
.hid.bLength = sizeof(usb_hid_descriptor_t),\
.hid.bDescriptorType = USB_DT_HID,\
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
.hid.wDescriptorLength = LE16(sizeof(udi_hid_mou_report_desc_t)),\
.ep.bLength = sizeof(usb_ep_desc_t),\
.ep.bDescriptorType = USB_DT_ENDPOINT,\
.ep.bEndpointAddress = UDI_HID_MOU_EP_IN | USB_EP_DIR_IN,\
.ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep.wMaxPacketSize = LE16(UDI_HID_MOU_EP_SIZE),\
.ep.bInterval = MOU_POLLING_INTERVAL,\
}
//no set report buffer
//report buffer
#define UDI_HID_MOU_REPORT_SIZE 5 //MOU PDS
extern uint8_t udi_hid_mou_report[UDI_HID_MOU_REPORT_SIZE];
COMPILER_PACK_RESET()
#endif //MOU
// **********************************************************************
// RAW Descriptor structure and content
// **********************************************************************
#ifdef RAW
COMPILER_PACK_SET(1)
typedef struct {
usb_iface_desc_t iface;
usb_hid_descriptor_t hid;
usb_ep_desc_t ep_out;
usb_ep_desc_t ep_in;
} udi_hid_raw_desc_t;
typedef struct {
uint8_t array[27];
} udi_hid_raw_report_desc_t;
#define UDI_HID_RAW_DESC {\
.iface.bLength = sizeof(usb_iface_desc_t),\
.iface.bDescriptorType = USB_DT_INTERFACE,\
.iface.bInterfaceNumber = RAW_INTERFACE,\
.iface.bAlternateSetting = 0,\
.iface.bNumEndpoints = 2,\
.iface.bInterfaceClass = HID_CLASS,\
.iface.bInterfaceSubClass = HID_SUB_CLASS_NOBOOT,\
.iface.bInterfaceProtocol = HID_SUB_CLASS_NOBOOT,\
.iface.iInterface = UDI_HID_RAW_STRING_ID,\
.hid.bLength = sizeof(usb_hid_descriptor_t),\
.hid.bDescriptorType = USB_DT_HID,\
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
.hid.wDescriptorLength = LE16(sizeof(udi_hid_raw_report_desc_t)),\
.ep_out.bLength = sizeof(usb_ep_desc_t),\
.ep_out.bDescriptorType = USB_DT_ENDPOINT,\
.ep_out.bEndpointAddress = UDI_HID_RAW_EP_OUT | USB_EP_DIR_OUT,\
.ep_out.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep_out.wMaxPacketSize = LE16(RAW_EPSIZE),\
.ep_out.bInterval = RAW_POLLING_INTERVAL,\
.ep_in.bLength = sizeof(usb_ep_desc_t),\
.ep_in.bDescriptorType = USB_DT_ENDPOINT,\
.ep_in.bEndpointAddress = UDI_HID_RAW_EP_IN | USB_EP_DIR_IN,\
.ep_in.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep_in.wMaxPacketSize = LE16(RAW_EPSIZE),\
.ep_in.bInterval = RAW_POLLING_INTERVAL,\
}
#define UDI_HID_RAW_REPORT_SIZE RAW_EPSIZE
extern uint8_t udi_hid_raw_report_set[UDI_HID_RAW_REPORT_SIZE];
//report buffer
extern uint8_t udi_hid_raw_report[UDI_HID_RAW_REPORT_SIZE];
COMPILER_PACK_RESET()
#endif //RAW
// **********************************************************************
// CDC Descriptor structure and content
// **********************************************************************
#ifdef CDC
COMPILER_PACK_SET(1)
typedef struct {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
le16_t bcdCDC;
} usb_cdc_hdr_desc_t;
typedef struct {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bmCapabilities;
uint8_t bDataInterface;
} usb_cdc_call_mgmt_desc_t;
typedef struct {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bmCapabilities;
} usb_cdc_acm_desc_t;
typedef struct {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bMasterInterface;
uint8_t bSlaveInterface0;
} usb_cdc_union_desc_t;
typedef struct {
usb_association_desc_t iaface;
usb_iface_desc_t iface_c;
usb_cdc_hdr_desc_t fd;
usb_cdc_call_mgmt_desc_t mfd;
usb_cdc_acm_desc_t acmd;
usb_cdc_union_desc_t ufd;
usb_ep_desc_t ep_c;
usb_iface_desc_t iface_d;
usb_ep_desc_t ep_tx;
usb_ep_desc_t ep_rx;
} udi_cdc_desc_t;
#define CDC_DESCRIPTOR {\
.iaface.bLength = sizeof(usb_association_desc_t),\
.iaface.bDescriptorType = USB_DT_IAD,\
.iaface.bFirstInterface = CDC_STATUS_INTERFACE,\
.iaface.bInterfaceCount = 2,\
.iaface.bFunctionClass = CDC_CLASS_DEVICE,\
.iaface.bFunctionSubClass = CDC_SUBCLASS_ACM,\
.iaface.bFunctionProtocol = CDC_PROTOCOL_V25TER,\
.iaface.iFunction = 0,\
.iface_c.bLength = sizeof(usb_iface_desc_t),\
.iface_c.bDescriptorType = USB_DT_INTERFACE,\
.iface_c.bInterfaceNumber = CDC_STATUS_INTERFACE,\
.iface_c.bAlternateSetting = 0,\
.iface_c.bNumEndpoints = 1,\
.iface_c.bInterfaceClass = 0x02,\
.iface_c.bInterfaceSubClass = 0x02,\
.iface_c.bInterfaceProtocol = CDC_PROTOCOL_V25TER,\
.iface_c.iInterface = 0,\
.fd.bFunctionLength = sizeof(usb_cdc_hdr_desc_t),\
.fd.bDescriptorType = CDC_CS_INTERFACE,\
.fd.bDescriptorSubtype = CDC_SCS_HEADER,\
.fd.bcdCDC = 0x0110,\
.mfd.bFunctionLength = sizeof(usb_cdc_call_mgmt_desc_t),\
.mfd.bDescriptorType = CDC_CS_INTERFACE,\
.mfd.bDescriptorSubtype = CDC_SCS_CALL_MGMT,\
.mfd.bmCapabilities = CDC_CALL_MGMT_SUPPORTED,\
.mfd.bDataInterface = CDC_DATA_INTERFACE,\
.acmd.bFunctionLength = sizeof(usb_cdc_acm_desc_t),\
.acmd.bDescriptorType = CDC_CS_INTERFACE,\
.acmd.bDescriptorSubtype = CDC_SCS_ACM,\
.acmd.bmCapabilities = CDC_ACM_SUPPORT_LINE_REQUESTS,\
.ufd.bFunctionLength = sizeof(usb_cdc_union_desc_t),\
.ufd.bDescriptorType = CDC_CS_INTERFACE,\
.ufd.bDescriptorSubtype = CDC_SCS_UNION,\
.ufd.bMasterInterface = CDC_STATUS_INTERFACE,\
.ufd.bSlaveInterface0 = CDC_DATA_INTERFACE,\
.ep_c.bLength = sizeof(usb_ep_desc_t),\
.ep_c.bDescriptorType = USB_DT_ENDPOINT,\
.ep_c.bEndpointAddress = CDC_ACM_ENDPOINT | USB_EP_DIR_IN,\
.ep_c.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep_c.wMaxPacketSize = LE16(CDC_ACM_SIZE),\
.ep_c.bInterval = CDC_EP_INTERVAL_STATUS,\
.iface_d.bLength = sizeof(usb_iface_desc_t),\
.iface_d.bDescriptorType = USB_DT_INTERFACE,\
.iface_d.bInterfaceNumber = CDC_DATA_INTERFACE,\
.iface_d.bAlternateSetting = 0,\
.iface_d.bNumEndpoints = 2,\
.iface_d.bInterfaceClass = CDC_CLASS_DATA,\
.iface_d.bInterfaceSubClass = 0,\
.iface_d.bInterfaceProtocol = 0,\
.iface_d.iInterface = 0,\
.ep_rx.bLength = sizeof(usb_ep_desc_t),\
.ep_rx.bDescriptorType = USB_DT_ENDPOINT,\
.ep_rx.bEndpointAddress = CDC_RX_ENDPOINT | USB_EP_DIR_OUT,\
.ep_rx.bmAttributes = USB_EP_TYPE_BULK,\
.ep_rx.wMaxPacketSize = LE16(CDC_RX_SIZE),\
.ep_rx.bInterval = CDC_EP_INTERVAL_DATA,\
.ep_tx.bLength = sizeof(usb_ep_desc_t),\
.ep_tx.bDescriptorType = USB_DT_ENDPOINT,\
.ep_tx.bEndpointAddress = CDC_TX_ENDPOINT | USB_EP_DIR_IN,\
.ep_tx.bmAttributes = USB_EP_TYPE_BULK,\
.ep_tx.wMaxPacketSize = LE16(CDC_TX_SIZE),\
.ep_tx.bInterval = CDC_EP_INTERVAL_DATA,\
}
COMPILER_PACK_RESET()
#endif //CDC
// **********************************************************************
// CONFIGURATION Descriptor structure and content
// **********************************************************************
COMPILER_PACK_SET(1)
typedef struct {
usb_conf_desc_t conf;
#ifdef KBD
udi_hid_kbd_desc_t hid_kbd;
#endif
#ifdef MOU
udi_hid_mou_desc_t hid_mou;
#endif
#ifdef EXK
udi_hid_exk_desc_t hid_exk;
#endif
#ifdef RAW
udi_hid_raw_desc_t hid_raw;
#endif
#ifdef CON
udi_hid_con_desc_t hid_con;
#endif
#ifdef NKRO
udi_hid_nkro_desc_t hid_nkro;
#endif
#ifdef MIDI
udi_hid_midi_desc_t hid_midi;
#endif
#ifdef CDC
udi_cdc_desc_t cdc_serial;
#endif
} udc_desc_t;
COMPILER_PACK_RESET()
#endif //_UDI_DEVICE_CONF_H_

View File

@ -0,0 +1,32 @@
/*
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/>.
*/
#ifndef _UDI_DEVICE_EPSIZE_H_
#define _UDI_DEVICE_EPSIZE_H_
#define KEYBOARD_EPSIZE 8
#define MOUSE_EPSIZE 8
#define EXTRAKEY_EPSIZE 8
#define RAW_EPSIZE 64
#define CONSOLE_EPSIZE 32
#define NKRO_EPSIZE 32
#define MIDI_STREAM_EPSIZE 64
#define CDC_NOTIFICATION_EPSIZE 8
#define CDC_EPSIZE 16
#endif //_UDI_DEVICE_EPSIZE_H_

View File

@ -0,0 +1,162 @@
/**
* \file
*
* \brief USB Device Human Interface Device (HID) interface.
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#include "conf_usb.h"
#include "usb_protocol.h"
#include "udd.h"
#include "udc.h"
#include "udi_hid.h"
/**
* \ingroup udi_hid_group
* \defgroup udi_hid_group_internal Implementation of HID common library
* @{
*/
/**
* \brief Send the specific descriptors requested by SETUP request
*
* \retval true if the descriptor is supported
*/
static bool udi_hid_reqstdifaceget_descriptor(uint8_t *report_desc);
bool udi_hid_setup( uint8_t *rate, uint8_t *protocol, uint8_t *report_desc, bool (*setup_report)(void) )
{
if (Udd_setup_is_in()) {
// Requests Interface GET
if (Udd_setup_type() == USB_REQ_TYPE_STANDARD) {
// Requests Standard Interface Get
switch (udd_g_ctrlreq.req.bRequest) {
case USB_REQ_GET_DESCRIPTOR:
return udi_hid_reqstdifaceget_descriptor(report_desc);
}
}
if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
// Requests Class Interface Get
switch (udd_g_ctrlreq.req.bRequest) {
case USB_REQ_HID_GET_REPORT:
return setup_report();
case USB_REQ_HID_GET_IDLE:
udd_g_ctrlreq.payload = rate;
udd_g_ctrlreq.payload_size = 1;
return true;
case USB_REQ_HID_GET_PROTOCOL:
udd_g_ctrlreq.payload = protocol;
udd_g_ctrlreq.payload_size = 1;
return true;
}
}
}
if (Udd_setup_is_out()) {
// Requests Interface SET
if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
// Requests Class Interface Set
switch (udd_g_ctrlreq.req.bRequest) {
case USB_REQ_HID_SET_REPORT:
return setup_report();
case USB_REQ_HID_SET_IDLE:
*rate = udd_g_ctrlreq.req.wValue >> 8;
return true;
case USB_REQ_HID_SET_PROTOCOL:
if (0 != udd_g_ctrlreq.req.wLength)
return false;
*protocol = udd_g_ctrlreq.req.wValue;
return true;
}
}
}
return false; // Request not supported
}
//---------------------------------------------
//------- Internal routines
static bool udi_hid_reqstdifaceget_descriptor(uint8_t *report_desc)
{
usb_hid_descriptor_t UDC_DESC_STORAGE *ptr_hid_desc;
// Get the USB descriptor which is located after the interface descriptor
// This descriptor must be the HID descriptor
ptr_hid_desc = (usb_hid_descriptor_t UDC_DESC_STORAGE *) ((uint8_t *)
udc_get_interface_desc() + sizeof(usb_iface_desc_t));
if (USB_DT_HID != ptr_hid_desc->bDescriptorType)
return false;
// The SETUP request can ask for:
// - an USB_DT_HID descriptor
// - or USB_DT_HID_REPORT descriptor
// - or USB_DT_HID_PHYSICAL descriptor
if (USB_DT_HID == (uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) {
// USB_DT_HID descriptor requested then send it
udd_g_ctrlreq.payload = (uint8_t *) ptr_hid_desc;
udd_g_ctrlreq.payload_size =
min(udd_g_ctrlreq.req.wLength,
ptr_hid_desc->bLength);
return true;
}
// The HID_X descriptor requested must correspond to report type
// included in the HID descriptor
if (ptr_hid_desc->bRDescriptorType ==
(uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) {
// Send HID Report descriptor given by high level
udd_g_ctrlreq.payload = report_desc;
udd_g_ctrlreq.payload_size =
min(udd_g_ctrlreq.req.wLength,
le16_to_cpu(ptr_hid_desc->wDescriptorLength));
return true;
}
return false;
}
//@}

View File

@ -0,0 +1,85 @@
/**
* \file
*
* \brief USB Device Human Interface Device (HID) interface definitions.
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDI_HID_H_
#define _UDI_HID_H_
#include "conf_usb.h"
#include "usb_protocol.h"
#include "usb_protocol_hid.h"
#include "udd.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \ingroup udi_group
* \defgroup udi_hid_group USB Device Interface (UDI) for Human Interface Device (HID)
*
* Common library for all Human Interface Device (HID) implementation.
*
* @{
*/
/**
* \brief Decode HID setup request
*
* \param rate Pointer on rate of current HID interface
* \param protocol Pointer on protocol of current HID interface
* \param report_desc Pointer on report descriptor of current HID interface
* \param set_report Pointer on set_report callback of current HID interface
*
* \return \c 1 if function was successfully done, otherwise \c 0.
*/
bool udi_hid_setup( uint8_t *rate, uint8_t *protocol, uint8_t *report_desc, bool (*setup_report)(void) );
//@}
#ifdef __cplusplus
}
#endif
#endif // _UDI_HID_H_

View File

@ -0,0 +1,845 @@
/**
* \file
*
* \brief USB Device Human Interface Device (HID) keyboard interface.
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#include "samd51j18a.h"
#include "conf_usb.h"
#include "usb_protocol.h"
#include "udd.h"
#include "udc.h"
#include "udi_device_conf.h"
#include "udi_hid.h"
#include "udi_hid_kbd.h"
#include <string.h>
//***************************************************************************
// KBD
//***************************************************************************
#ifdef KBD
bool udi_hid_kbd_enable(void);
void udi_hid_kbd_disable(void);
bool udi_hid_kbd_setup(void);
uint8_t udi_hid_kbd_getsetting(void);
UDC_DESC_STORAGE udi_api_t udi_api_hid_kbd = {
.enable = (bool(*)(void))udi_hid_kbd_enable,
.disable = (void (*)(void))udi_hid_kbd_disable,
.setup = (bool(*)(void))udi_hid_kbd_setup,
.getsetting = (uint8_t(*)(void))udi_hid_kbd_getsetting,
.sof_notify = NULL,
};
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_kbd_rate;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_kbd_protocol;
COMPILER_WORD_ALIGNED
uint8_t udi_hid_kbd_report_set;
bool udi_hid_kbd_b_report_valid;
COMPILER_WORD_ALIGNED
uint8_t udi_hid_kbd_report[UDI_HID_KBD_REPORT_SIZE];
static bool udi_hid_kbd_b_report_trans_ongoing;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_kbd_report_trans[UDI_HID_KBD_REPORT_SIZE];
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE udi_hid_kbd_report_desc_t udi_hid_kbd_report_desc = {
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x05, 0x07, // Usage Page (Keyboard)
0x19, 0xE0, // Usage Minimum (224)
0x29, 0xE7, // Usage Maximum (231)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x81, 0x01, // Input (Constant)
0x19, 0x00, // Usage Minimum (0)
0x29, 0x65, // Usage Maximum (101)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x65, // Logical Maximum (101)
0x75, 0x08, // Report Size (8)
0x95, 0x06, // Report Count (6)
0x81, 0x00, // Input (Data, Array)
0x05, 0x08, // Usage Page (LED)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x05, // Report Count (5)
0x91, 0x02, // Output (Data, Variable, Absolute)
0x95, 0x03, // Report Count (3)
0x91, 0x01, // Output (Constant)
0xC0 // End Collection
}
};
static bool udi_hid_kbd_setreport(void);
static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
static void udi_hid_kbd_setreport_valid(void);
bool udi_hid_kbd_enable(void)
{
// Initialize internal values
udi_hid_kbd_rate = 0;
udi_hid_kbd_protocol = 0;
udi_hid_kbd_b_report_trans_ongoing = false;
memset(udi_hid_kbd_report, 0, UDI_HID_KBD_REPORT_SIZE);
udi_hid_kbd_b_report_valid = false;
return UDI_HID_KBD_ENABLE_EXT();
}
void udi_hid_kbd_disable(void)
{
UDI_HID_KBD_DISABLE_EXT();
}
bool udi_hid_kbd_setup(void)
{
return udi_hid_setup(&udi_hid_kbd_rate,
&udi_hid_kbd_protocol,
(uint8_t *) &udi_hid_kbd_report_desc,
udi_hid_kbd_setreport);
}
uint8_t udi_hid_kbd_getsetting(void)
{
return 0;
}
static bool udi_hid_kbd_setreport(void)
{
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
&& (1 == udd_g_ctrlreq.req.wLength)) {
// Report OUT type on report ID 0 from USB Host
udd_g_ctrlreq.payload = &udi_hid_kbd_report_set;
udd_g_ctrlreq.callback = udi_hid_kbd_setreport_valid;
udd_g_ctrlreq.payload_size = 1;
return true;
}
return false;
}
bool udi_hid_kbd_send_report(void)
{
if (!main_b_kbd_enable) {
return false;
}
if (udi_hid_kbd_b_report_trans_ongoing) {
return false;
}
memcpy(udi_hid_kbd_report_trans, udi_hid_kbd_report,
UDI_HID_KBD_REPORT_SIZE);
udi_hid_kbd_b_report_valid = false;
udi_hid_kbd_b_report_trans_ongoing =
udd_ep_run(UDI_HID_KBD_EP_IN | USB_EP_DIR_IN,
false,
udi_hid_kbd_report_trans,
UDI_HID_KBD_REPORT_SIZE,
udi_hid_kbd_report_sent);
return udi_hid_kbd_b_report_trans_ongoing;
}
static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
{
UNUSED(status);
UNUSED(nb_sent);
UNUSED(ep);
udi_hid_kbd_b_report_trans_ongoing = false;
if (udi_hid_kbd_b_report_valid) {
udi_hid_kbd_send_report();
}
}
static void udi_hid_kbd_setreport_valid(void)
{
//UDI_HID_KBD_CHANGE_LED(udi_hid_kbd_report_set);
}
#endif //KBD
//********************************************************************************************
// NKRO Keyboard
//********************************************************************************************
#ifdef NKRO
bool udi_hid_nkro_enable(void);
void udi_hid_nkro_disable(void);
bool udi_hid_nkro_setup(void);
uint8_t udi_hid_nkro_getsetting(void);
UDC_DESC_STORAGE udi_api_t udi_api_hid_nkro = {
.enable = (bool(*)(void))udi_hid_nkro_enable,
.disable = (void (*)(void))udi_hid_nkro_disable,
.setup = (bool(*)(void))udi_hid_nkro_setup,
.getsetting = (uint8_t(*)(void))udi_hid_nkro_getsetting,
.sof_notify = NULL,
};
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_nkro_rate;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_nkro_protocol;
COMPILER_WORD_ALIGNED
uint8_t udi_hid_nkro_report_set;
bool udi_hid_nkro_b_report_valid;
COMPILER_WORD_ALIGNED
uint8_t udi_hid_nkro_report[UDI_HID_NKRO_REPORT_SIZE];
static bool udi_hid_nkro_b_report_trans_ongoing;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_nkro_report_trans[UDI_HID_NKRO_REPORT_SIZE];
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE udi_hid_nkro_report_desc_t udi_hid_nkro_report_desc = {
{
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x06, // Usage (Keyboard),
0xA1, 0x01, // Collection (Application) - Keyboard,
//Mods
0x75, 0x01, // Report Size (1),
0x95, 0x08, // Report Count (8),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0xE0, // Usage Minimum (224),
0x29, 0xE7, // Usage Maximum (231),
0x81, 0x02, // Input (Data, Variable, Absolute),
//LED Report
0x75, 0x01, // Report Size (1),
0x95, 0x05, // Report Count (5),
0x05, 0x08, // Usage Page (LEDs),
0x19, 0x01, // Usage Minimum (1),
0x29, 0x05, // Usage Maximum (5),
0x91, 0x02, // Output (Data, Variable, Absolute),
//LED Report Padding
0x75, 0x03, // Report Size (3),
0x95, 0x01, // Report Count (1),
0x91, 0x03, // Output (Constant),
//Main keys
0x75, 0x01, // Report Size (1),
0x95, 0xF8, // Report Count (248),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0x00, // Usage Minimum (0),
0x29, 0xF7, // Usage Maximum (247),
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield),
0xc0, // End Collection - Keyboard
}
};
static bool udi_hid_nkro_setreport(void);
static void udi_hid_nkro_setreport_valid(void);
static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
bool udi_hid_nkro_enable(void)
{
// Initialize internal values
udi_hid_nkro_rate = 0;
udi_hid_nkro_protocol = 0;
udi_hid_nkro_b_report_trans_ongoing = false;
memset(udi_hid_nkro_report, 0, UDI_HID_NKRO_REPORT_SIZE);
udi_hid_nkro_b_report_valid = false;
return UDI_HID_NKRO_ENABLE_EXT();
}
void udi_hid_nkro_disable(void)
{
UDI_HID_NKRO_DISABLE_EXT();
}
bool udi_hid_nkro_setup(void)
{
return udi_hid_setup(&udi_hid_nkro_rate,
&udi_hid_nkro_protocol,
(uint8_t *) &udi_hid_nkro_report_desc,
udi_hid_nkro_setreport);
}
uint8_t udi_hid_nkro_getsetting(void)
{
return 0;
}
//keyboard receives LED report here
static bool udi_hid_nkro_setreport(void)
{
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
&& (1 == udd_g_ctrlreq.req.wLength)) {
// Report OUT type on report ID 0 from USB Host
udd_g_ctrlreq.payload = &udi_hid_nkro_report_set;
udd_g_ctrlreq.callback = udi_hid_nkro_setreport_valid; //must call routine to transform setreport to LED state
udd_g_ctrlreq.payload_size = 1;
return true;
}
return false;
}
bool udi_hid_nkro_send_report(void)
{
if (!main_b_nkro_enable) {
return false;
}
if (udi_hid_nkro_b_report_trans_ongoing) {
return false;
}
memcpy(udi_hid_nkro_report_trans, udi_hid_nkro_report,UDI_HID_NKRO_REPORT_SIZE);
udi_hid_nkro_b_report_valid = false;
udi_hid_nkro_b_report_trans_ongoing =
udd_ep_run(UDI_HID_NKRO_EP_IN | USB_EP_DIR_IN,
false,
udi_hid_nkro_report_trans,
UDI_HID_NKRO_REPORT_SIZE,
udi_hid_nkro_report_sent);
return udi_hid_nkro_b_report_trans_ongoing;
}
static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
{
UNUSED(status);
UNUSED(nb_sent);
UNUSED(ep);
udi_hid_nkro_b_report_trans_ongoing = false;
if (udi_hid_nkro_b_report_valid) {
udi_hid_nkro_send_report();
}
}
static void udi_hid_nkro_setreport_valid(void)
{
//UDI_HID_NKRO_CHANGE_LED(udi_hid_nkro_report_set);
}
#endif //NKRO
//********************************************************************************************
// EXK (extra-keys) SYS-CTRL Keyboard
//********************************************************************************************
#ifdef EXK
bool udi_hid_exk_enable(void);
void udi_hid_exk_disable(void);
bool udi_hid_exk_setup(void);
uint8_t udi_hid_exk_getsetting(void);
UDC_DESC_STORAGE udi_api_t udi_api_hid_exk = {
.enable = (bool(*)(void))udi_hid_exk_enable,
.disable = (void (*)(void))udi_hid_exk_disable,
.setup = (bool(*)(void))udi_hid_exk_setup,
.getsetting = (uint8_t(*)(void))udi_hid_exk_getsetting,
.sof_notify = NULL,
};
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_exk_rate;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_exk_protocol;
COMPILER_WORD_ALIGNED
uint8_t udi_hid_exk_report_set;
bool udi_hid_exk_b_report_valid;
COMPILER_WORD_ALIGNED
udi_hid_exk_report_t udi_hid_exk_report;
static bool udi_hid_exk_b_report_trans_ongoing;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_exk_report_trans[UDI_HID_EXK_REPORT_SIZE];
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {
{
// System Control Collection (8 bits)
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x80, // Usage (System Control),
0xA1, 0x01, // Collection (Application),
0x85, 0x02, // Report ID (2) (System),
0x16, 0x01, 0x00, // Logical Minimum (1),
0x26, 0x03, 0x00, // Logical Maximum (3),
0x1A, 0x81, 0x00, // Usage Minimum (81) (System Power Down),
0x2A, 0x83, 0x00, // Usage Maximum (83) (System Wake Up),
0x75, 0x10, // Report Size (16),
0x95, 0x01, // Report Count (1),
0x81, 0x00, // Input (Data, Array),
0xC0, // End Collection - System Control
// Consumer Control Collection - Media Keys (16 bits)
0x05, 0x0C, // Usage Page (Consumer),
0x09, 0x01, // Usage (Consumer Control),
0xA1, 0x01, // Collection (Application),
0x85, 0x03, // Report ID (3) (Consumer),
0x16, 0x01, 0x00, // Logical Minimum (1),
0x26, 0x9C, 0x02, // Logical Maximum (668),
0x1A, 0x01, 0x00, // Usage Minimum (1),
0x2A, 0x9C, 0x02, // Usage Maximum (668),
0x75, 0x10, // Report Size (16),
0x95, 0x01, // Report Count (1),
0x81, 0x00, // Input (Data, Array),
0xC0, // End Collection - Consumer Control
}
};
static bool udi_hid_exk_setreport(void);
static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
static void udi_hid_exk_setreport_valid(void);
bool udi_hid_exk_enable(void)
{
// Initialize internal values
udi_hid_exk_rate = 0;
udi_hid_exk_protocol = 0;
udi_hid_exk_b_report_trans_ongoing = false;
memset(udi_hid_exk_report.raw, 0, UDI_HID_EXK_REPORT_SIZE);
udi_hid_exk_b_report_valid = false;
return UDI_HID_EXK_ENABLE_EXT();
}
void udi_hid_exk_disable(void)
{
UDI_HID_EXK_DISABLE_EXT();
}
bool udi_hid_exk_setup(void)
{
return udi_hid_setup(&udi_hid_exk_rate,
&udi_hid_exk_protocol,
(uint8_t *) &udi_hid_exk_report_desc,
udi_hid_exk_setreport);
}
uint8_t udi_hid_exk_getsetting(void)
{
return 0;
}
static bool udi_hid_exk_setreport(void)
{
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
&& (1 == udd_g_ctrlreq.req.wLength)) {
// Report OUT type on report ID 0 from USB Host
udd_g_ctrlreq.payload = &udi_hid_exk_report_set;
udd_g_ctrlreq.callback = udi_hid_exk_setreport_valid;
udd_g_ctrlreq.payload_size = 1;
return true;
}
return false;
}
bool udi_hid_exk_send_report(void)
{
if (!main_b_exk_enable) {
return false;
}
if (udi_hid_exk_b_report_trans_ongoing) {
return false;
}
memcpy(udi_hid_exk_report_trans, udi_hid_exk_report.raw, UDI_HID_EXK_REPORT_SIZE);
udi_hid_exk_b_report_valid = false;
udi_hid_exk_b_report_trans_ongoing =
udd_ep_run(UDI_HID_EXK_EP_IN | USB_EP_DIR_IN,
false,
udi_hid_exk_report_trans,
UDI_HID_EXK_REPORT_SIZE,
udi_hid_exk_report_sent);
return udi_hid_exk_b_report_trans_ongoing;
}
static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
{
UNUSED(status);
UNUSED(nb_sent);
UNUSED(ep);
udi_hid_exk_b_report_trans_ongoing = false;
if (udi_hid_exk_b_report_valid) {
udi_hid_exk_send_report();
}
}
static void udi_hid_exk_setreport_valid(void)
{
}
#endif //EXK
//********************************************************************************************
// MOU Mouse
//********************************************************************************************
#ifdef MOU
bool udi_hid_mou_enable(void);
void udi_hid_mou_disable(void);
bool udi_hid_mou_setup(void);
uint8_t udi_hid_mou_getsetting(void);
UDC_DESC_STORAGE udi_api_t udi_api_hid_mou = {
.enable = (bool(*)(void))udi_hid_mou_enable,
.disable = (void (*)(void))udi_hid_mou_disable,
.setup = (bool(*)(void))udi_hid_mou_setup,
.getsetting = (uint8_t(*)(void))udi_hid_mou_getsetting,
.sof_notify = NULL,
};
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_mou_rate;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_mou_protocol;
//COMPILER_WORD_ALIGNED
//uint8_t udi_hid_mou_report_set; //No set report
bool udi_hid_mou_b_report_valid;
COMPILER_WORD_ALIGNED
uint8_t udi_hid_mou_report[UDI_HID_MOU_REPORT_SIZE];
static bool udi_hid_mou_b_report_trans_ongoing;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_mou_report_trans[UDI_HID_MOU_REPORT_SIZE];
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE udi_hid_mou_report_desc_t udi_hid_mou_report_desc = {
{
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x02, // Usage (Mouse),
0xA1, 0x01, // Collection (Application),
0x09, 0x01, // Usage (Pointer),
0xA1, 0x00, // Collection (Physical),
0x05, 0x09, // Usage Page (Buttons),
0x19, 0x01, // Usage Minimum (01),
0x29, 0x05, // Usage Maximun (05),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x95, 0x05, // Report Count (5),
0x75, 0x01, // Report Size (1),
0x81, 0x02, // Input (Data, Variable, Absolute), ;5 button bits
0x95, 0x01, // Report Count (1),
0x75, 0x03, // Report Size (3),
0x81, 0x01, // Input (Constant), ;3 bit padding,
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x30, // Usage (X),
0x09, 0x31, // Usage (Y),
0x15, 0x81, // Logical Minimum (-127),
0x25, 0x7F, // Logical Maximum (127),
0x95, 0x02, // Report Count (2),
0x75, 0x08, // Report Size (8),
0x81, 0x06, // Input (Data, Variable, Relative), ;2 position bytes (X & Y),
0x09, 0x38, // Usage (Wheel),
0x15, 0x81, // Logical Minimum (-127),
0x25, 0x7F, // Logical Maximum (127),
0x95, 0x01, // Report Count (1),
0x75, 0x08, // Report Size (8),
0x81, 0x06, // Input (Data, Variable, Relative),
0x05, 0x0C, // Usage Page (Consumer),
0x0A, 0x38, 0x02, // Usage (AC Pan (Horizontal wheel)),
0x15, 0x81, // Logical Minimum (-127),
0x25, 0x7F, // Logical Maximum (127),
0x95, 0x01, // Report Count (1),
0x75, 0x08, // Report Size (8),
0x81, 0x06, // Input (Data, Variable, Relative),
0xC0, // End Collection,
0xC0, // End Collection
}
};
static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
bool udi_hid_mou_enable(void)
{
// Initialize internal values
udi_hid_mou_rate = 0;
udi_hid_mou_protocol = 0;
udi_hid_mou_b_report_trans_ongoing = false;
memset(udi_hid_mou_report, 0, UDI_HID_MOU_REPORT_SIZE);
udi_hid_mou_b_report_valid = false;
return UDI_HID_MOU_ENABLE_EXT();
}
void udi_hid_mou_disable(void)
{
UDI_HID_MOU_DISABLE_EXT();
}
bool udi_hid_mou_setup(void)
{
return udi_hid_setup(&udi_hid_mou_rate,
&udi_hid_mou_protocol,
(uint8_t *) &udi_hid_mou_report_desc,
NULL);
}
uint8_t udi_hid_mou_getsetting(void)
{
return 0;
}
bool udi_hid_mou_send_report(void)
{
if (!main_b_mou_enable) {
return false;
}
if (udi_hid_mou_b_report_trans_ongoing) {
return false;
}
memcpy(udi_hid_mou_report_trans, udi_hid_mou_report, UDI_HID_MOU_REPORT_SIZE);
udi_hid_mou_b_report_valid = false;
udi_hid_mou_b_report_trans_ongoing =
udd_ep_run(UDI_HID_MOU_EP_IN | USB_EP_DIR_IN,
false,
udi_hid_mou_report_trans,
UDI_HID_MOU_REPORT_SIZE,
udi_hid_mou_report_sent);
return udi_hid_mou_b_report_trans_ongoing;
}
static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
{
UNUSED(status);
UNUSED(nb_sent);
UNUSED(ep);
udi_hid_mou_b_report_trans_ongoing = false;
if (udi_hid_mou_b_report_valid) {
udi_hid_mou_send_report();
}
}
#endif //MOU
//********************************************************************************************
// RAW
//********************************************************************************************
#ifdef RAW
bool udi_hid_raw_enable(void);
void udi_hid_raw_disable(void);
bool udi_hid_raw_setup(void);
uint8_t udi_hid_raw_getsetting(void);
UDC_DESC_STORAGE udi_api_t udi_api_hid_raw = {
.enable = (bool(*)(void))udi_hid_raw_enable,
.disable = (void (*)(void))udi_hid_raw_disable,
.setup = (bool(*)(void))udi_hid_raw_setup,
.getsetting = (uint8_t(*)(void))udi_hid_raw_getsetting,
.sof_notify = NULL,
};
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_raw_rate;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_raw_protocol;
COMPILER_WORD_ALIGNED
uint8_t udi_hid_raw_report_set[UDI_HID_RAW_REPORT_SIZE];
static bool udi_hid_raw_b_report_valid;
COMPILER_WORD_ALIGNED
uint8_t udi_hid_raw_report[UDI_HID_RAW_REPORT_SIZE];
static bool udi_hid_raw_b_report_trans_ongoing;
COMPILER_WORD_ALIGNED
static uint8_t udi_hid_raw_report_trans[UDI_HID_RAW_REPORT_SIZE];
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE udi_hid_raw_report_desc_t udi_hid_raw_report_desc = {
{
0x06, // Usage Page (Vendor Defined)
0xFF, 0xFF,
0x0A, // Usage (Mouse)
0xFF, 0xFF,
0xA1, 0x01, // Collection (Application)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0xFF, // Logical Maximum (255)
0x95, 0x40, // Report Count
0x09, 0x01, // Usage (Input)
0x81, 0x02, // Input (Data
0x95, 0x40, // Report Count
0x09, 0x02, // Usage (Output)
0x91, 0x02, // Output (Data
0xC0, // End Collection - Consumer Control
}
};
static bool udi_hid_raw_setreport(void);
static void udi_hid_raw_setreport_valid(void);
static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
bool udi_hid_raw_enable(void)
{
// Initialize internal values
udi_hid_raw_rate = 0;
udi_hid_raw_protocol = 0;
udi_hid_raw_b_report_trans_ongoing = false;
memset(udi_hid_raw_report, 0, UDI_HID_RAW_REPORT_SIZE);
udi_hid_raw_b_report_valid = false;
return UDI_HID_RAW_ENABLE_EXT();
}
void udi_hid_raw_disable(void)
{
UDI_HID_RAW_DISABLE_EXT();
}
bool udi_hid_raw_setup(void)
{
return udi_hid_setup(&udi_hid_raw_rate,
&udi_hid_raw_protocol,
(uint8_t *) &udi_hid_raw_report_desc,
udi_hid_raw_setreport);
}
uint8_t udi_hid_raw_getsetting(void)
{
return 0;
}
static bool udi_hid_raw_setreport(void)
{
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
&& (UDI_HID_RAW_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) {
// Report OUT type on report ID 0 from USB Host
udd_g_ctrlreq.payload = udi_hid_raw_report_set;
udd_g_ctrlreq.callback = udi_hid_raw_setreport_valid; //must call routine to transform setreport to LED state
udd_g_ctrlreq.payload_size = UDI_HID_RAW_REPORT_SIZE;
return true;
}
return false;
}
bool udi_hid_raw_send_report(void)
{
if (!main_b_raw_enable) {
return false;
}
if (udi_hid_raw_b_report_trans_ongoing) {
return false;
}
memcpy(udi_hid_raw_report_trans, udi_hid_raw_report,UDI_HID_RAW_REPORT_SIZE);
udi_hid_raw_b_report_valid = false;
udi_hid_raw_b_report_trans_ongoing =
udd_ep_run(UDI_HID_RAW_EP_IN | USB_EP_DIR_IN,
false,
udi_hid_raw_report_trans,
UDI_HID_RAW_REPORT_SIZE,
udi_hid_raw_report_sent);
return udi_hid_raw_b_report_trans_ongoing;
}
static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
{
UNUSED(status);
UNUSED(nb_sent);
UNUSED(ep);
udi_hid_raw_b_report_trans_ongoing = false;
if (udi_hid_raw_b_report_valid) {
udi_hid_raw_send_report();
}
}
static void udi_hid_raw_setreport_valid(void)
{
}
#endif //RAW

View File

@ -0,0 +1,109 @@
/**
* \file
*
* \brief USB Device Human Interface Device (HID) keyboard interface.
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDC_HID_KBD_H_
#define _UDC_HID_KBD_H_
#include "udc_desc.h"
#include "udi.h"
#ifdef __cplusplus
extern "C" {
#endif
//******************************************************************************
// Keyboard interface definitions
//******************************************************************************
#ifdef KBD
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_kbd;
extern bool udi_hid_kbd_b_report_valid;
extern uint8_t udi_hid_kbd_report_set;
bool udi_hid_kbd_send_report(void);
#endif //KBD
//********************************************************************************************
// NKRO Keyboard
//********************************************************************************************
#ifdef NKRO
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_nkro;
extern bool udi_hid_nkro_b_report_valid;
bool udi_hid_nkro_send_report(void);
#endif //NKRO
//********************************************************************************************
// SYS-CTRL interface
//********************************************************************************************
#ifdef EXK
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_exk;
extern bool udi_hid_exk_b_report_valid;
extern uint8_t udi_hid_exk_report_set;
bool udi_hid_exk_send_report(void);
#endif //EXK
//********************************************************************************************
// MOU Mouse
//********************************************************************************************
#ifdef MOU
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_mou;
extern bool udi_hid_mou_b_report_valid;
bool udi_hid_mou_send_report(void);
#endif //MOU
//********************************************************************************************
// RAW Raw
//********************************************************************************************
#ifdef RAW
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_raw;
bool udi_hid_raw_send_report(void);
#endif //RAW
//@}
#ifdef __cplusplus
}
#endif
#endif // _UDC_HID_KBD_H_

View File

@ -0,0 +1,60 @@
/**
* \file
*
* \brief Default HID keyboard configuration for a USB Device
* with a single interface HID keyboard
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UDI_HID_KBD_CONF_H_
#define _UDI_HID_KBD_CONF_H_
/**
* \addtogroup udi_hid_keyboard_group_single_desc
* @{
*/
#include "udi_device_conf.h"
#include "udi_hid_kbd.h"
#endif // _UDI_HID_KBD_CONF_H_

View File

@ -0,0 +1,179 @@
/**
* \file
*
* \brief Default descriptors for a USB Device
* with a single interface HID keyboard
*
* Copyright (c) 2009-2016 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#include "conf_usb.h"
#include "usb_protocol.h"
#include "udc_desc.h"
#include "udi_device_conf.h"
#include "udi_hid_kbd.h"
#include "udi_cdc.h"
/**
* \ingroup udi_hid_keyboard_group
* \defgroup udi_hid_keyboard_group_single_desc USB device descriptors for a single interface
*
* The following structures provide the USB device descriptors required
* for USB Device with a single interface HID keyboard.
*
* It is ready to use and do not require more definition.
* @{
*/
//! USB Device Descriptor
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE usb_dev_desc_t udc_device_desc = {
.bLength = sizeof(usb_dev_desc_t),
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = LE16(USB_V2_0),
.bDeviceClass = DEVICE_CLASS,
.bDeviceSubClass = DEVICE_SUBCLASS,
.bDeviceProtocol = DEVICE_PROTOCOL,
.bMaxPacketSize0 = USB_DEVICE_EP_CTRL_SIZE,
.idVendor = LE16(USB_DEVICE_VENDOR_ID),
.idProduct = LE16(USB_DEVICE_PRODUCT_ID),
.bcdDevice = LE16(USB_DEVICE_VERSION),
#ifdef USB_DEVICE_MANUFACTURE_NAME
.iManufacturer = 1,
#else
.iManufacturer = 0, // No manufacture string
#endif
#ifdef USB_DEVICE_PRODUCT_NAME
.iProduct = 2,
#else
.iProduct = 0, // No product string
#endif
#if (defined USB_DEVICE_SERIAL_NAME || defined USB_DEVICE_GET_SERIAL_NAME_POINTER)
.iSerialNumber = 3,
#else
.iSerialNumber = 0, // No serial string
#endif
.bNumConfigurations = 1
};
#if 0
#ifdef USB_DEVICE_HS_SUPPORT
//! USB Device Qualifier Descriptor for HS
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE usb_dev_qual_desc_t udc_device_qual = {
.bLength = sizeof(usb_dev_qual_desc_t),
.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
.bcdUSB = LE16(USB_V2_0),
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = USB_DEVICE_EP_CTRL_SIZE,
.bNumConfigurations = 1
};
#endif
#endif
//! USB Device Configuration Descriptor filled for FS and HS
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE udc_desc_t udc_desc = {
.conf.bLength = sizeof(usb_conf_desc_t),
.conf.bDescriptorType = USB_DT_CONFIGURATION,
.conf.wTotalLength = LE16(sizeof(udc_desc_t)),
.conf.bNumInterfaces = USB_DEVICE_NB_INTERFACE,
.conf.bConfigurationValue = 1,
.conf.iConfiguration = 0,
.conf.bmAttributes = /* USB_CONFIG_ATTR_MUST_SET | */ USB_DEVICE_ATTR,
.conf.bMaxPower = USB_CONFIG_MAX_POWER(USB_DEVICE_POWER),
#ifdef KBD
.hid_kbd = UDI_HID_KBD_DESC,
#endif
#ifdef RAW
.hid_raw = UDI_HID_RAW_DESC,
#endif
#ifdef MOU
.hid_mou = UDI_HID_MOU_DESC,
#endif
#ifdef EXK
.hid_exk = UDI_HID_EXK_DESC,
#endif
#ifdef NKRO
.hid_nkro = UDI_HID_NKRO_DESC,
#endif
#ifdef CDC
.cdc_serial = CDC_DESCRIPTOR,
#endif
};
UDC_DESC_STORAGE udi_api_t *udi_apis[USB_DEVICE_NB_INTERFACE] = {
#ifdef KBD
&udi_api_hid_kbd,
#endif
#ifdef RAW
&udi_api_hid_raw,
#endif
#ifdef MOU
&udi_api_hid_mou,
#endif
#ifdef EXK
&udi_api_hid_exk,
#endif
#ifdef NKRO
&udi_api_hid_nkro,
#endif
#ifdef CDC
&udi_api_cdc_comm, &udi_api_cdc_data,
#endif
};
//! Add UDI with USB Descriptors FS & HS
UDC_DESC_STORAGE udc_config_speed_t udc_config_fshs[1] = {{
.desc = (usb_conf_desc_t UDC_DESC_STORAGE*)&udc_desc,
.udi_apis = udi_apis,
}};
//! Add all information about USB Device in global structure for UDC
UDC_DESC_STORAGE udc_config_t udc_config = {
.confdev_lsfs = &udc_device_desc,
.conf_lsfs = udc_config_fshs,
};
//@}
//@}

View File

@ -0,0 +1,106 @@
/**
* \file
*
* \brief User Interface
*
* Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef ARM_MATH_CM4
#define ARM_MATH_CM4
#endif
#undef LITTLE_ENDIAN //redefined in samd51j18a.h
#include "samd51j18a.h"
#include "ui.h"
volatile uint8_t usb_state;
//! Sequence process running each \c SEQUENCE_PERIOD ms
#define SEQUENCE_PERIOD 150
#if 0
/* Interrupt on "pin change" from push button to do wakeup on USB
* Note:
* This interrupt is enable when the USB host enable remote wakeup feature
* This interrupt wakeup the CPU if this one is in idle mode
*/
static void ui_wakeup_handler(void)
{
/* It is a wakeup then send wakeup USB */
udc_remotewakeup();
}
#endif
void ui_init(void)
{
usb_state = USB_STATE_POWERUP;
}
void ui_powerdown(void)
{
usb_state = USB_STATE_POWERDOWN;
}
void ui_wakeup_enable(void)
{
}
void ui_wakeup_disable(void)
{
}
void ui_wakeup(void)
{
usb_state = USB_STATE_POWERUP;
}
void ui_process(uint16_t framenumber)
{
}
void ui_kbd_led(uint8_t value)
{
}

View File

@ -0,0 +1,82 @@
/**
* \file
*
* \brief Common User Interface for HID Keyboard application
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _UI_H_
#define _UI_H_
extern volatile uint8_t usb_state;
#define USB_STATE_UNKNOWN 0
#define USB_STATE_POWERDOWN 1
#define USB_STATE_POWERUP 2
//! \brief Initializes the user interface
void ui_init(void);
//! \brief Enters the user interface in power down mode
void ui_powerdown(void);
//! \brief Enables the asynchronous interrupts of the user interface
void ui_wakeup_enable(void);
//! \brief Disables the asynchronous interrupts of the user interface
void ui_wakeup_disable(void);
//! \brief Exits the user interface of power down mode
void ui_wakeup(void);
/*! \brief This process is called each 1ms
* It is called only if the USB interface is enabled.
*
* \param framenumber Current frame number
*/
void ui_process(uint16_t framenumber);
/*! \brief Turn on or off the keyboard LEDs
*/
void ui_kbd_led(uint8_t value);
#endif // _UI_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,492 @@
/**
* \file
*
* \brief SAM USB Driver
*
* Copyright (C) 2014-2016 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef USB_H_INCLUDED
#define USB_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup asfdoc_sam0_usb_group SAM Universal Serial Bus (USB)
*
* The Universal Serial Bus (USB) module complies with the USB 2.1 specification.
*
* The following peripherals are used by this module:
* - USB (Universal Serial Bus)
*
* The following devices can use this module:
* - Atmel | SMART SAM D51
*
* The USB module covers following mode:
* \if USB_DEVICE_MODE
* - USB Device Mode
* \endif
* \if USB_HOST_MODE
* - USB Host Mode
* \endif
*
* The USB module covers following speed:
* \if USB_HS_MODE
* - USB High Speed (480Mbit/s)
* \endif
* - USB Full Speed (12Mbit/s)
* \if USB_LS_MODE
* - USB Low Speed (1.5Mbit/s)
* \endif
*
* \if USB_LPM_MODE
* The USB module supports Link Power Management (LPM-L1) protocol.
* \endif
*
* USB support needs whole set of enumeration process, to make the device
* recognizable and usable. The USB driver is designed to interface to the
* USB Stack in Atmel Software Framework (ASF).
*
* \if USB_DEVICE_MODE
* \section asfdoc_sam0_usb_device USB Device Mode
* The ASF USB Device Stack has defined the USB Device Driver (UDD) interface,
* to support USB device operations. The USB module device driver complies with
* this interface, so that the USB Device Stack can work based on the
* USB module.
*
* Refer to <a href="http://www.atmel.com/images/doc8360.pdf">
* "ASF - USB Device Stack"</a> for more details.
* \endif
*
* \if USB_HOST_MODE
* \section adfdoc_sam0_usb_host USB Host Mode
* The ASF USB Host Stack has defined the USB Host Driver (UHD) interface,
* to support USB host operations. The USB module host driver complies with
* this interface, so that the USB Host Stack can work based on the USB module.
*
* Refer to <a href="http://www.atmel.com/images/doc8486.pdf">
* "ASF - USB Host Stack"</a> for more details.
* \endif
*/
/** Enum for the speed status for the USB module */
enum usb_speed {
USB_SPEED_LOW,
USB_SPEED_FULL,
};
/** Enum for the possible callback types for the USB in host module */
enum usb_host_callback {
USB_HOST_CALLBACK_SOF,
USB_HOST_CALLBACK_RESET,
USB_HOST_CALLBACK_WAKEUP,
USB_HOST_CALLBACK_DNRSM,
USB_HOST_CALLBACK_UPRSM,
USB_HOST_CALLBACK_RAMACER,
USB_HOST_CALLBACK_CONNECT,
USB_HOST_CALLBACK_DISCONNECT,
USB_HOST_CALLBACK_N,
};
/** Enum for the possible callback types for the USB pipe in host module */
enum usb_host_pipe_callback {
USB_HOST_PIPE_CALLBACK_TRANSFER_COMPLETE,
USB_HOST_PIPE_CALLBACK_ERROR,
USB_HOST_PIPE_CALLBACK_SETUP,
USB_HOST_PIPE_CALLBACK_STALL,
USB_HOST_PIPE_CALLBACK_N,
};
/**
* \brief Host pipe types.
*/
enum usb_host_pipe_type {
USB_HOST_PIPE_TYPE_DISABLE,
USB_HOST_PIPE_TYPE_CONTROL,
USB_HOST_PIPE_TYPE_ISO,
USB_HOST_PIPE_TYPE_BULK,
USB_HOST_PIPE_TYPE_INTERRUPT,
USB_HOST_PIPE_TYPE_EXTENDED,
};
/**
* \brief Host pipe token types.
*/
enum usb_host_pipe_token {
USB_HOST_PIPE_TOKEN_SETUP,
USB_HOST_PIPE_TOKEN_IN,
USB_HOST_PIPE_TOKEN_OUT,
};
/**
* \brief Enumeration for the possible callback types for the USB in device module
*/
enum usb_device_callback {
USB_DEVICE_CALLBACK_SOF,
USB_DEVICE_CALLBACK_RESET,
USB_DEVICE_CALLBACK_WAKEUP,
USB_DEVICE_CALLBACK_RAMACER,
USB_DEVICE_CALLBACK_SUSPEND,
USB_DEVICE_CALLBACK_LPMNYET,
USB_DEVICE_CALLBACK_LPMSUSP,
USB_DEVICE_CALLBACK_N,
};
/**
* \brief Enumeration for the possible callback types for the USB endpoint in device module
*/
enum usb_device_endpoint_callback {
USB_DEVICE_ENDPOINT_CALLBACK_TRCPT,
USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL,
USB_DEVICE_ENDPOINT_CALLBACK_RXSTP,
USB_DEVICE_ENDPOINT_CALLBACK_STALL,
USB_DEVICE_EP_CALLBACK_N,
};
/**
* \brief Device Endpoint types.
*/
enum usb_device_endpoint_type {
USB_DEVICE_ENDPOINT_TYPE_DISABLE,
USB_DEVICE_ENDPOINT_TYPE_CONTROL,
USB_DEVICE_ENDPOINT_TYPE_ISOCHRONOUS,
USB_DEVICE_ENDPOINT_TYPE_BULK,
USB_DEVICE_ENDPOINT_TYPE_INTERRUPT,
};
/**
* \brief Endpoint Size
*/
enum usb_endpoint_size {
USB_ENDPOINT_8_BYTE,
USB_ENDPOINT_16_BYTE,
USB_ENDPOINT_32_BYTE,
USB_ENDPOINT_64_BYTE,
USB_ENDPOINT_128_BYTE,
USB_ENDPOINT_256_BYTE,
USB_ENDPOINT_512_BYTE,
USB_ENDPOINT_1023_BYTE,
};
/**
* \brief Link Power Management Handshake.
*/
enum usb_device_lpm_mode {
USB_DEVICE_LPM_NOT_SUPPORT,
USB_DEVICE_LPM_ACK,
USB_DEVICE_LPM_NYET,
};
/**
* \brief Module structure
*/
struct usb_module;
/**
* \name Host Callback Functions Types
* @{
*/
typedef void (*usb_host_callback_t)(struct usb_module *module_inst);
typedef void (*usb_host_pipe_callback_t)(struct usb_module *module_inst, void *);
/** @} */
/**
* \name Device Callback Functions Types
* @{
*/
typedef void (*usb_device_callback_t)(struct usb_module *module_inst, void* pointer);
typedef void (*usb_device_endpoint_callback_t)(struct usb_module *module_inst, void* pointer);
/** @} */
/** USB configurations */
struct usb_config {
/** \c true for host, \c false for device. */
bool select_host_mode;
/** When \c true the module is enabled during standby. */
bool run_in_standby;
/** Generic Clock Generator source channel. */
// enum gclk_generator source_generator;
uint8_t source_generator;
/** Speed mode */
//enum usb_speed speed_mode;
uint8_t speed_mode;
};
/**
* \brief USB software module instance structure.
*
* USB software module instance structure, used to retain software state
* information of an associated hardware module instance.
*
*/
struct usb_module {
/** Hardware module pointer of the associated USB peripheral. */
Usb *hw;
/** Array to store device related callback functions */
usb_device_callback_t device_callback[USB_DEVICE_CALLBACK_N];
usb_device_endpoint_callback_t device_endpoint_callback[USB_EPT_NUM][USB_DEVICE_EP_CALLBACK_N];
/** Bit mask for device callbacks registered */
uint16_t device_registered_callback_mask;
/** Bit mask for device callbacks enabled */
uint16_t device_enabled_callback_mask;
/** Bit mask for device endpoint callbacks registered */
uint8_t device_endpoint_registered_callback_mask[USB_EPT_NUM];
/** Bit mask for device endpoint callbacks enabled */
uint8_t device_endpoint_enabled_callback_mask[USB_EPT_NUM];
};
/** USB device endpoint configurations */
struct usb_device_endpoint_config {
/** device address */
uint8_t ep_address;
/** endpoint size */
enum usb_endpoint_size ep_size;
/** automatic zero length packet mode, \c true to enable */
bool auto_zlp;
/** type of endpoint with Bank */
enum usb_device_endpoint_type ep_type;
};
/** USB device endpoint callback status parameter structure */
struct usb_endpoint_callback_parameter {
uint16_t received_bytes;
uint16_t sent_bytes;
uint16_t out_buffer_size;
uint8_t endpoint_address;
};
void usb_enable(struct usb_module *module_inst);
void usb_disable(struct usb_module *module_inst);
/**
* \brief Get the status of USB module's state machine
*
* \param module_inst Pointer to USB module instance
*/
static inline uint8_t usb_get_state_machine_status(struct usb_module *module_inst)
{
/* Sanity check arguments */
Assert(module_inst);
Assert(module_inst->hw);
return module_inst->hw->DEVICE.FSMSTATUS.reg;
}
void usb_get_config_defaults(struct usb_config *module_config);
enum status_code usb_init(struct usb_module *module_inst, Usb *const hw,
struct usb_config *module_config);
/**
* \brief Attach USB device to the bus
*
* \param module_inst Pointer to USB device module instance
*/
static inline void usb_device_attach(struct usb_module *module_inst)
{
module_inst->hw->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_DETACH;
}
/**
* \brief Detach USB device from the bus
*
* \param module_inst Pointer to USB device module instance
*/
static inline void usb_device_detach(struct usb_module *module_inst)
{
module_inst->hw->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_DETACH;
}
/**
* \brief Get the speed mode of USB device
*
* \param module_inst Pointer to USB device module instance
* \return USB Speed mode (\ref usb_speed).
*/
static inline enum usb_speed usb_device_get_speed(struct usb_module *module_inst)
{
if (!(module_inst->hw->DEVICE.STATUS.reg & USB_DEVICE_STATUS_SPEED_Msk)) {
return USB_SPEED_FULL;
} else {
return USB_SPEED_LOW;
}
}
/**
* \brief Get the address of USB device
*
* \param module_inst Pointer to USB device module instance
* \return USB device address value.
*/
static inline uint8_t usb_device_get_address(struct usb_module *module_inst)
{
return ((uint8_t)(module_inst->hw->DEVICE.DADD.bit.DADD));
}
/**
* \brief Set the speed mode of USB device
*
* \param module_inst Pointer to USB device module instance
* \param address USB device address value
*/
static inline void usb_device_set_address(struct usb_module *module_inst, uint8_t address)
{
module_inst->hw->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | address;
}
/**
* \brief Get the frame number of USB device
*
* \param module_inst Pointer to USB device module instance
* \return USB device frame number value.
*/
static inline uint16_t usb_device_get_frame_number(struct usb_module *module_inst)
{
return ((uint16_t)(module_inst->hw->DEVICE.FNUM.bit.FNUM));
}
/**
* \brief Get the micro-frame number of USB device
*
* \param module_inst Pointer to USB device module instance
* \return USB device micro-frame number value.
*/
static inline uint16_t usb_device_get_micro_frame_number(struct usb_module *module_inst)
{
return ((uint16_t)(module_inst->hw->DEVICE.FNUM.reg));
}
/**
* \brief USB device send the resume wakeup
*
* \param module_inst Pointer to USB device module instance
*/
static inline void usb_device_send_remote_wake_up(struct usb_module *module_inst)
{
module_inst->hw->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_UPRSM;
}
/**
* \brief USB device set the LPM mode
*
* \param module_inst Pointer to USB device module instance
* \param lpm_mode LPM mode
*/
static inline void usb_device_set_lpm_mode(struct usb_module *module_inst,
enum usb_device_lpm_mode lpm_mode)
{
module_inst->hw->DEVICE.CTRLB.bit.LPMHDSK = lpm_mode;
}
/**
* \name USB Device Callback Management
* @{
*/
enum status_code usb_device_register_callback(struct usb_module *module_inst,
enum usb_device_callback callback_type,
usb_device_callback_t callback_func);
enum status_code usb_device_unregister_callback(struct usb_module *module_inst,
enum usb_device_callback callback_type);
enum status_code usb_device_enable_callback(struct usb_module *module_inst,
enum usb_device_callback callback_type);
enum status_code usb_device_disable_callback(struct usb_module *module_inst,
enum usb_device_callback callback_type);
/** @} */
/**
* \name USB Device Endpoint Configuration
* @{
*/
void usb_device_endpoint_get_config_defaults(struct usb_device_endpoint_config *ep_config);
enum status_code usb_device_endpoint_set_config(struct usb_module *module_inst,
struct usb_device_endpoint_config *ep_config);
bool usb_device_endpoint_is_configured(struct usb_module *module_inst, uint8_t ep);
/** @} */
/**
* \name USB Device Endpoint Callback Management
* @{
*/
enum status_code usb_device_endpoint_register_callback(
struct usb_module *module_inst, uint8_t ep_num,
enum usb_device_endpoint_callback callback_type,
usb_device_endpoint_callback_t callback_func);
enum status_code usb_device_endpoint_unregister_callback(
struct usb_module *module_inst, uint8_t ep_num,
enum usb_device_endpoint_callback callback_type);
enum status_code usb_device_endpoint_enable_callback(
struct usb_module *module_inst, uint8_t ep,
enum usb_device_endpoint_callback callback_type);
enum status_code usb_device_endpoint_disable_callback(
struct usb_module *module_inst, uint8_t ep,
enum usb_device_endpoint_callback callback_type);
/** @} */
/**
* \name USB Device Endpoint Job Management
* @{
*/
enum status_code usb_device_endpoint_write_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
uint8_t* pbuf, uint32_t buf_size);
enum status_code usb_device_endpoint_read_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
uint8_t* pbuf, uint32_t buf_size);
enum status_code usb_device_endpoint_setup_buffer_job(struct usb_module *module_inst,
uint8_t* pbuf);
void usb_device_endpoint_abort_job(struct usb_module *module_inst, uint8_t ep);
/** @} */
/**
* \name USB Device Endpoint Operations
* @{
*/
bool usb_device_endpoint_is_halted(struct usb_module *module_inst, uint8_t ep);
void usb_device_endpoint_set_halt(struct usb_module *module_inst, uint8_t ep);
void usb_device_endpoint_clear_halt(struct usb_module *module_inst, uint8_t ep);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* USB_H_INCLUDED */

View File

@ -0,0 +1,412 @@
/*
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/>.
*/
#include "arm_atsam_protocol.h"
#include <string.h>
Usb2422 USB2422_shadow;
unsigned char i2c0_buf[34];
const uint16_t MFRNAME[] = { 'M','a','s','s','d','r','o','p',' ','I','n','c','.' }; //Massdrop Inc.
const uint16_t PRDNAME[] = { 'M','a','s','s','d','r','o','p',' ','H','u','b' }; //Massdrop Hub
#ifndef MD_BOOTLOADER
//Serial number reported stops before first found space character or at last found character
const uint16_t SERNAME[] = { 'U','n','a','v','a','i','l','a','b','l','e' }; //Unavailable
#else
//In production, this field is found, modified, and offset noted as the last 32-bit word in the bootloader space
//The offset allows the application to use the factory programmed serial (which may differ from the physical serial label)
//Serial number reported stops before first found space character or when max size is reached
__attribute__((__aligned__(4)))
const uint16_t SERNAME[BOOTLOADER_SERIAL_MAX_SIZE] = { 'M','D','H','U','B','B','O','O','T','L','0','0','0','0','0','0','0','0','0','0' };
//NOTE: Serial replacer will not write a string longer than given here as a precaution, so give enough
// space as needed and adjust BOOTLOADER_SERIAL_MAX_SIZE to match amount given
#endif //MD_BOOTLOADER
uint8_t usb_host_port;
#ifndef MD_BOOTLOADER
uint8_t usb_extra_state;
uint8_t usb_extra_manual;
uint8_t usb_gcr_auto;
#endif //MD_BOOTLOADER
uint16_t adc_extra;
void USB_write2422_block(void)
{
unsigned char *dest = i2c0_buf;
unsigned char *src;
unsigned char *base = (unsigned char *)&USB2422_shadow;
DBGC(DC_USB_WRITE2422_BLOCK_BEGIN);
for (src = base; src < base + 256; src += 32)
{
dest[0] = src - base;
dest[1] = 32;
memcpy(&dest[2], src, 32);
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);
}
DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE);
}
void USB2422_init(void)
{
Gclk *pgclk = GCLK;
Mclk *pmclk = MCLK;
Port *pport = PORT;
Oscctrl *posc = OSCCTRL;
Usb *pusb = USB;
Srdata_t *pspi = &srdata;
DBGC(DC_USB2422_INIT_BEGIN);
while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB2422_INIT_WAIT_5V_LOW); }
//setup peripheral and synchronous bus clocks to USB
pgclk->PCHCTRL[10].bit.GEN = 0;
pgclk->PCHCTRL[10].bit.CHEN = 1;
pmclk->AHBMASK.bit.USB_ = 1;
pmclk->APBBMASK.bit.USB_ = 1;
//setup port pins for D-, D+, and SOF_1KHZ
pport->Group[0].PMUX[12].reg = 0x77; //PA24, PA25, function column H for USB D-, D+
pport->Group[0].PINCFG[24].bit.PMUXEN = 1;
pport->Group[0].PINCFG[25].bit.PMUXEN = 1;
pport->Group[1].PMUX[11].bit.PMUXE = 7; //PB22, function column H for USB SOF_1KHz output
pport->Group[1].PINCFG[22].bit.PMUXEN = 1;
//configure and enable DFLL for USB clock recovery mode at 48MHz
posc->DFLLCTRLA.bit.ENABLE = 0;
while (posc->DFLLSYNC.bit.ENABLE) { DBGC(DC_USB2422_INIT_OSC_SYNC_DISABLING); }
while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_1); }
posc->DFLLCTRLB.bit.USBCRM = 1;
while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_2); }
posc->DFLLCTRLB.bit.MODE = 1;
while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_3); }
posc->DFLLCTRLB.bit.QLDIS = 0;
while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_4); }
posc->DFLLCTRLB.bit.CCDIS = 1;
posc->DFLLMUL.bit.MUL = 0xBB80; //4800 x 1KHz
while (posc->DFLLSYNC.bit.DFLLMUL) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLMUL); }
posc->DFLLCTRLA.bit.ENABLE = 1;
while (posc->DFLLSYNC.bit.ENABLE) { DBGC(DC_USB2422_INIT_OSC_SYNC_ENABLING); }
pusb->DEVICE.CTRLA.bit.SWRST = 1;
while (pusb->DEVICE.SYNCBUSY.bit.SWRST) { DBGC(DC_USB2422_INIT_USB_SYNC_SWRST); }
while (pusb->DEVICE.CTRLA.bit.SWRST) { DBGC(DC_USB2422_INIT_USB_WAIT_SWRST); }
//calibration from factory presets
pusb->DEVICE.PADCAL.bit.TRANSN = (USB_FUSES_TRANSN_ADDR >> USB_FUSES_TRANSN_Pos) & USB_FUSES_TRANSN_Msk;
pusb->DEVICE.PADCAL.bit.TRANSP = (USB_FUSES_TRANSP_ADDR >> USB_FUSES_TRANSP_Pos) & USB_FUSES_TRANSP_Msk;
pusb->DEVICE.PADCAL.bit.TRIM = (USB_FUSES_TRIM_ADDR >> USB_FUSES_TRIM_Pos) & USB_FUSES_TRIM_Msk;
//device mode, enabled
pusb->DEVICE.CTRLB.bit.SPDCONF = 0; //full speed
pusb->DEVICE.CTRLA.bit.MODE = 0;
pusb->DEVICE.CTRLA.bit.ENABLE = 1;
while (pusb->DEVICE.SYNCBUSY.bit.ENABLE) { DBGC(DC_USB2422_INIT_USB_SYNC_ENABLING); }
pusb->DEVICE.QOSCTRL.bit.DQOS = 2;
pusb->DEVICE.QOSCTRL.bit.CQOS = 2;
pport->Group[USB2422_HUB_ACTIVE_GROUP].PINCFG[USB2422_HUB_ACTIVE_PIN].bit.INEN = 1;
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();
CLK_delay_us(100);
#ifndef MD_BOOTLOADER
usb_extra_manual = 0;
usb_gcr_auto = 1;
#endif //MD_BOOTLOADER
DBGC(DC_USB2422_INIT_COMPLETE);
}
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);
DBGC(DC_USB_RESET_COMPLETE);
}
void USB_configure(void)
{
Usb2422 *pusb2422 = &USB2422_shadow;
memset(pusb2422, 0, sizeof(Usb2422));
uint16_t *serial_use = (uint16_t *)SERNAME; //Default to use SERNAME from this file
uint8_t serial_length = sizeof(SERNAME) / sizeof(uint16_t); //Default to use SERNAME from this file
#ifndef MD_BOOTLOADER
uint32_t serial_ptrloc = (uint32_t)&_srom - 4;
#else //MD_BOOTLOADER
uint32_t serial_ptrloc = (uint32_t)&_erom - 4;
#endif //MD_BOOTLOADER
uint32_t serial_address = *(uint32_t *)serial_ptrloc; //Address of bootloader's serial number if available
DBGC(DC_USB_CONFIGURE_BEGIN);
if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) //Check for factory programmed serial address
{
if ((serial_address & 0xFF) % 4 == 0) //Check alignment
{
serial_use = (uint16_t *)(serial_address);
serial_length = 0;
while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) &&
serial_length < BOOTLOADER_SERIAL_MAX_SIZE)
{
serial_length++;
DBGC(DC_USB_CONFIGURE_GET_SERIAL);
}
}
}
//configure Usb2422 registers
pusb2422->VID.reg = 0x04D8; // from Microchip 4/19/2018
pusb2422->PID.reg = 0xEEC5; // from Microchip 4/19/2018 = Massdrop, Inc. USB Hub
pusb2422->DID.reg = 0x0101; // BCD 01.01
pusb2422->CFG1.bit.SELF_BUS_PWR = 1; // self powered for now
pusb2422->CFG1.bit.HS_DISABLE = 1; // full or high speed
//pusb2422->CFG2.bit.COMPOUND = 0; // compound device
pusb2422->CFG3.bit.STRING_EN = 1; // strings enabled
//pusb2422->NRD.bit.PORT2_NR = 0; // MCU is non-removable
pusb2422->MAXPB.reg = 20; // 0mA
pusb2422->HCMCB.reg = 20; // 0mA
pusb2422->MFRSL.reg = sizeof(MFRNAME) / sizeof(uint16_t);
pusb2422->PRDSL.reg = sizeof(PRDNAME) / sizeof(uint16_t);
pusb2422->SERSL.reg = serial_length;
memcpy(pusb2422->MFRSTR, MFRNAME, sizeof(MFRNAME));
memcpy(pusb2422->PRDSTR, PRDNAME, sizeof(PRDNAME));
memcpy(pusb2422->SERSTR, serial_use, serial_length * sizeof(uint16_t));
//pusb2422->BOOSTUP.bit.BOOST=3; //upstream port
//pusb2422->BOOSTDOWN.bit.BOOST1=0; // extra port
//pusb2422->BOOSTDOWN.bit.BOOST2=2; //MCU is close
pusb2422->STCD.bit.USB_ATTACH = 1;
USB_write2422_block();
adc_extra = 0;
DBGC(DC_USB_CONFIGURE_COMPLETE);
}
uint16_t USB_active(void)
{
return (PORT->Group[USB2422_HUB_ACTIVE_GROUP].IN.reg & (1 << USB2422_HUB_ACTIVE_PIN)) != 0;
}
void USB_set_host_by_voltage(void)
{
//UP is upstream device (HOST)
//DN1 is downstream device (EXTRA)
//DN2 is keyboard (KEYB)
DBGC(DC_USB_SET_HOST_BY_VOLTAGE_BEGIN);
usb_host_port = USB_HOST_PORT_UNKNOWN;
#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
SPI_WriteSRData();
CLK_delay_ms(250);
while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB_SET_HOST_5V_LOW_WAITING); }
v_con_1 = adc_get(ADC_CON1);
v_con_2 = adc_get(ADC_CON2);
v_con_1_boot = v_con_1;
v_con_2_boot = v_con_2;
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
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
SPI_WriteSRData();
srdata.bit.E_UP_N = 0; //HOST enable
SPI_WriteSRData();
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
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
SPI_WriteSRData();
srdata.bit.E_UP_N = 0; //HOST enable
SPI_WriteSRData();
usb_host_port = USB_HOST_PORT_2;
}
#ifndef MD_BOOTLOADER
usb_extra_state = USB_EXTRA_STATE_DISABLED;
#endif //MD_BOOTLOADER
USB_reset();
USB_configure();
DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE);
}
uint8_t USB2422_Port_Detect_Init(void)
{
uint32_t port_detect_retry_ms;
uint32_t tmod;
DBGC(DC_PORT_DETECT_INIT_BEGIN);
USB_set_host_by_voltage();
port_detect_retry_ms = CLK_get_ms() + PORT_DETECT_RETRY_INTERVAL;
while (!USB_active())
{
tmod = CLK_get_ms() % 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; }
}
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 (CLK_get_ms() > port_detect_retry_ms)
{
DBGC(DC_PORT_DETECT_INIT_FAILED);
return 0;
}
}
DBGC(DC_PORT_DETECT_INIT_COMPLETE);
return 1;
}
#ifndef MD_BOOTLOADER
void USB_ExtraSetState(uint8_t state)
{
uint8_t state_save = 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;
else return;
srdata.bit.E_DN1_N = !state;
SPI_WriteSRData();
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;
}
else if (usb_extra_state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) CDC_print("USB: Extra disabled until replug\r\n");
else CDC_print("USB: Extra state unknown\r\n");
}
void USB_HandleExtraDevice(void)
{
uint16_t adcval;
if (usb_host_port == USB_HOST_PORT_1) adcval = adc_get(ADC_CON2);
else if (usb_host_port == USB_HOST_PORT_2) adcval = adc_get(ADC_CON1);
else return;
adc_extra = adc_extra * 0.9 + adcval * 0.1;
//Check for a forced disable state (such as overload prevention)
if (usb_extra_state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG)
{
//Detect unplug and reset state to disabled
if (adc_extra > USB_EXTRA_ADC_THRESHOLD) usb_extra_state = USB_EXTRA_STATE_DISABLED;
return; //Return even if unplug detected
}
if (usb_extra_manual)
{
if (usb_extra_state == USB_EXTRA_STATE_DISABLED)
USB_ExtraSetState(USB_EXTRA_STATE_ENABLED);
return;
}
//dpf("a %i %i\r\n",adcval, adc_extra);
if (usb_extra_state == USB_EXTRA_STATE_DISABLED && adc_extra < USB_EXTRA_ADC_THRESHOLD) USB_ExtraSetState(USB_EXTRA_STATE_ENABLED);
else if (usb_extra_state == USB_EXTRA_STATE_ENABLED && adc_extra > USB_EXTRA_ADC_THRESHOLD) USB_ExtraSetState(USB_EXTRA_STATE_DISABLED);
}
#endif //MD_BOOTLOADER

View File

@ -0,0 +1,405 @@
/*
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/>.
*/
#ifndef _USB2422_H_
#define _USB2422_H_
#define USB2422_ALT67_1P0
#define REV_USB2422 0x100
#define USB2422_ADDR 0x58 //I2C device address, one instance
#define USB2422_HUB_ACTIVE_GROUP 0 //PA
#define USB2422_HUB_ACTIVE_PIN 18 //18
/* -------- USB2422_VID : (USB2422L Offset: 0x00) (R/W 16) Vendor ID -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint16_t VID_LSB : 8;
uint16_t VID_MSB : 8;
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} USB2422_VID_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PID : (USB2422L Offset: 0x02) (R/W 16) Product ID -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint16_t PID_LSB : 8;
uint16_t PID_MSB : 8;
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} USB2422_PID_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_DID : (USB2422L Offset: 0x04) (R/W 16) Device ID -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint16_t DID_LSB : 8;
uint16_t DID_MSB : 8;
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} USB2422_DID_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_CFG1 : (USB2422L Offset: 0x06) (R/W 8) Configuration Data Byte 1-------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t PORT_PWR : 1;
uint8_t CURRENT_SNS : 2;
uint8_t EOP_DISABLE : 1;
uint8_t MTT_ENABLE : 1;
uint8_t HS_DISABLE :1;
uint8_t :1;
uint8_t SELF_BUS_PWR : 1;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_CFG1_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_CFG2 : (USB2422L Offset: 0x07) (R/W 8) Configuration Data Byte 2-------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 3;
uint8_t COMPOUND : 1;
uint8_t OC_TIMER :2;
uint8_t :1;
uint8_t DYNAMIC : 1;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_CFG2_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_CFG3 : (USB2422L Offset: 0x08) (R/W 16) Configuration Data Byte 3-------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t STRING_EN : 1;
uint8_t :2;
uint8_t PRTMAP_EN :1;
uint8_t : 4;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_CFG3_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_NRD : (USB2422L Offset: 0x09) (R/W 8) Non Removable Device -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 5;
uint8_t PORT2_NR :1;
uint8_t PORT1_NR :1;
uint8_t : 1;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_NRD_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PDS : (USB2422L Offset: 0x0A) (R/W 8) Port Diable for Self-Powered Operation -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 1;
uint8_t PORT1_DIS :1;
uint8_t PORT2_DIS :1;
uint8_t : 5;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PDS_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PDB : (USB2422L Offset: 0x0B) (R/W 8) Port Diable for Bus-Powered Operation -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 1;
uint8_t PORT1_DIS :1;
uint8_t PORT2_DIS :1;
uint8_t : 5;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PDB_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_MAXPS : (USB2422L Offset: 0x0C) (R/W 8) Max Power for Self-Powered Operation -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t MAX_PWR_SP : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_MAXPS_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_MAXPB : (USB2422L Offset: 0x0D) (R/W 8) Max Power for Bus-Powered Operation -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t MAX_PWR_BP : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_MAXPB_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_HCMCS : (USB2422L Offset: 0x0E) (R/W 8) Hub Controller Max Current for Self-Powered Operation -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t HC_MAX_C_SP : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_HCMCS_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_HCMCB : (USB2422L Offset: 0x0F) (R/W 8) Hub Controller Max Current for Bus-Powered Operation -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t HC_MAX_C_BP : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_HCMCB_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PWRT : (USB2422L Offset: 0x10) (R/W 8) Power On Time -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t POWER_ON_TIME : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PWRT_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_LANGID LSB : (USB2422L Offset: 0x11) (R/W 16) Language ID -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t LANGID_LSB : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_LANGID_LSB_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_LANGID MSB : (USB2422L Offset: 0x12) (R/W 16) Language ID -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t LANGID_MSB : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_LANGID_MSB_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_MFRSL : (USB2422L Offset: 0x13) (R/W 8) Manufacturer String Length -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t MFR_STR_LEN : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_MFRSL_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PRDSL : (USB2422L Offset: 0x14) (R/W 8) Product String Length -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t PRD_STR_LEN : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PRDSL_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_SERSL : (USB2422L Offset: 0x15) (R/W 8) Serial String Length -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t SER_STR_LEN : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_SERSL_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_MFRSTR : (USB2422L Offset: 0x16-53) (R/W 8) Maufacturer String -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef uint16_t USB2422_MFRSTR_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PRDSTR : (USB2422L Offset: 0x54-91) (R/W 8) Product String -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef uint16_t USB2422_PRDSTR_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_SERSTR : (USB2422L Offset: 0x92-CF) (R/W 8) Serial String -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef uint16_t USB2422_SERSTR_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_BCEN : (USB2422L Offset: 0xD0) (R/W 8) Battery Charging Enable -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 1;
uint8_t PORT1_BCE :1;
uint8_t PORT2_BCE :1;
uint8_t : 5;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_BCEN_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_BOOSTUP : (USB2422L Offset: 0xF6) (R/W 8) Boost Upstream -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t BOOST :2;
uint8_t : 6;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_BOOSTUP_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_BOOSTDOWN : (USB2422L Offset: 0xF8) (R/W 8) Boost Downstream -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t BOOST1 :2;
uint8_t BOOST2 :2;
uint8_t : 4;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_BOOSTDOWN_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PRTSP : (USB2422L Offset: 0xFA) (R/W 8) Port Swap -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 1;
uint8_t PORT1_SP :1;
uint8_t PORT2_SP :1;
uint8_t : 5;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PRTSP_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PRTR12 : (USB2422L Offset: 0xFB) (R/W 8) Port 1/2 Remap -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t PORT1_REMAP: 4;
uint8_t PORT2_REMAP: 4;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PRTR12_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
#define USB2422_PRTR12_DISABLE 0
#define USB2422_PRT12_P2TOL1 1
#define USB2422_PRT12_P2XTOL2 2
#define USB2422_PRT12_P1TOL1 1
#define USB2422_PRT12_P1XTOL2 2
/* -------- USB2422_STCD : (USB2422L Offset: 0xFF) (R/W 8) Status Command -------- */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t USB_ATTACH: 1;
uint8_t RESET: 1;
uint8_t INTF_PWRDN: 1;
uint8_t : 5;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_STCD_Type;
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/** \brief USB2422 device hardware registers */
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef struct {
USB2422_VID_Type VID; /**< \brief Offset: 0x00*/
USB2422_PID_Type PID; /**< \brief Offset: 0x02*/
USB2422_DID_Type DID; /**< \brief Offset: 0x04*/
USB2422_CFG1_Type CFG1; /**< \brief Offset: 0x06*/
USB2422_CFG2_Type CFG2; /**< \brief Offset: 0x07*/
USB2422_CFG3_Type CFG3; /**< \brief Offset: 0x08*/
USB2422_NRD_Type NRD; /**< \brief Offset: 0x09*/
USB2422_PDS_Type PDS; /**< \brief Offset: 0x0A*/
USB2422_PDB_Type PDB; /**< \brief Offset: 0x0B*/
USB2422_MAXPS_Type MAXPS; /**< \brief Offset: 0x0C*/
USB2422_MAXPB_Type MAXPB; /**< \brief Offset: 0x0D*/
USB2422_HCMCS_Type HCMCS; /**< \brief Offset: 0x0E*/
USB2422_HCMCB_Type HCMCB; /**< \brief Offset: 0x0F*/
USB2422_PWRT_Type PWRT; /**< \brief Offset: 0x10*/
USB2422_LANGID_LSB_Type LANGID_LSB; /**< \brief Offset: 0x11*/
USB2422_LANGID_MSB_Type LANGID_MSB; /**< \brief Offset: 0x12*/
USB2422_MFRSL_Type MFRSL; /**< \brief Offset: 0x13*/
USB2422_PRDSL_Type PRDSL; /**< \brief Offset: 0x14*/
USB2422_SERSL_Type SERSL; /**< \brief Offset: 0x15*/
USB2422_MFRSTR_Type MFRSTR[31]; /**< \brief Offset: 0x16*/
USB2422_PRDSTR_Type PRDSTR[31]; /**< \brief Offset: 0x54*/
USB2422_SERSTR_Type SERSTR[31]; /**< \brief Offset: 0x92*/
USB2422_BCEN_Type BCEN; /**< \brief Offset: 0xD0*/
uint8_t Reserved1[0x25];
USB2422_BOOSTUP_Type BOOSTUP; /**< \brief Offset: 0xF6*/
uint8_t Reserved2[0x1];
USB2422_BOOSTDOWN_Type BOOSTDOWN; /**< \brief Offset: 0xF8*/
uint8_t Reserved3[0x1];
USB2422_PRTSP_Type PRTSP; /**< \brief Offset: 0xFA*/
USB2422_PRTR12_Type PRTR12; /**< \brief Offset: 0xFB*/
uint8_t Reserved4[0x3];
USB2422_STCD_Type STCD; /**< \brief Offset: 0xFF*/
} Usb2422;
#endif
#define PORT_DETECT_RETRY_INTERVAL 2000
#define USB_EXTRA_ADC_THRESHOLD 900
#define USB_EXTRA_STATE_DISABLED 0
#define USB_EXTRA_STATE_ENABLED 1
#define USB_EXTRA_STATE_UNKNOWN 2
#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3
#define USB_HOST_PORT_1 0
#define USB_HOST_PORT_2 1
#define USB_HOST_PORT_UNKNOWN 2
extern uint8_t usb_host_port;
extern uint8_t usb_extra_state;
extern uint8_t usb_extra_manual;
extern uint8_t usb_gcr_auto;
void USB2422_init(void);
void USB_reset(void);
void USB_configure(void);
uint16_t USB_active(void);
void USB_set_host_by_voltage(void);
uint16_t adc_get(uint8_t muxpos);
uint8_t USB2422_Port_Detect_Init(void);
void USB_HandleExtraDevice(void);
void USB_ExtraSetState(uint8_t state);
#endif //_USB2422_H_

View File

@ -0,0 +1,190 @@
/**
* \file
*
* \brief All USB VIDs and PIDs from Atmel USB applications
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _USB_ATMEL_H_
#define _USB_ATMEL_H_
/**
* \defgroup usb_group USB Stack
*
* This stack includes the USB Device Stack, USB Host Stack and common
* definitions.
* @{
*/
//! @}
/**
* \ingroup usb_group
* \defgroup usb_atmel_ids_group Atmel USB Identifiers
*
* This module defines Atmel PID and VIDs constants.
*
* @{
*/
//! \name Vendor Identifier assigned by USB org to ATMEL
#define USB_VID_ATMEL 0x03EB
//! \name Product Identifier assigned by ATMEL to AVR applications
//! @{
//! \name The range from 2000h to 20FFh is reserved to the old PID for C51, MEGA, and others.
//! @{
#define USB_PID_ATMEL_MEGA_HIDGENERIC 0x2013
#define USB_PID_ATMEL_MEGA_HIDKEYBOARD 0x2017
#define USB_PID_ATMEL_MEGA_CDC 0x2018
#define USB_PID_ATMEL_MEGA_AUDIO_IN 0x2019
#define USB_PID_ATMEL_MEGA_MS 0x201A
#define USB_PID_ATMEL_MEGA_AUDIO_IN_OUT 0x201B
#define USB_PID_ATMEL_MEGA_HIDMOUSE 0x201C
#define USB_PID_ATMEL_MEGA_HIDMOUSE_CERTIF_U4 0x201D
#define USB_PID_ATMEL_MEGA_CDC_MULTI 0x201E
#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_USBKEY 0x2022
#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_STK525 0x2023
#define USB_PID_ATMEL_MEGA_MS_2 0x2029
#define USB_PID_ATMEL_MEGA_MS_HIDMS 0x202A
#define USB_PID_ATMEL_MEGA_MS_3 0x2032
#define USB_PID_ATMEL_MEGA_LIBUSB 0x2050
//! @}
//! \name The range 2100h to 21FFh is reserved to PIDs for AVR Tools.
//! @{
#define USB_PID_ATMEL_XPLAINED 0x2122
#define USB_PID_ATMEL_XMEGA_USB_ZIGBIT_2_4GHZ 0x214A
#define USB_PID_ATMEL_XMEGA_USB_ZIGBIT_SUBGHZ 0x214B
//! @}
//! \name The range 2300h to 23FFh is reserved to PIDs for demo from ASF1.7=>
//! @{
#define USB_PID_ATMEL_UC3_ENUM 0x2300
#define USB_PID_ATMEL_UC3_MS 0x2301
#define USB_PID_ATMEL_UC3_MS_SDRAM_LOADER 0x2302
#define USB_PID_ATMEL_UC3_EVK1100_CTRLPANEL 0x2303
#define USB_PID_ATMEL_UC3_HID 0x2304
#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID 0x2305
#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID_MS 0x2306
#define USB_PID_ATMEL_UC3_CDC 0x2307
#define USB_PID_ATMEL_UC3_AUDIO_MICRO 0x2308
#define USB_PID_ATMEL_UC3_CDC_DEBUG 0x2310 // Virtual Com (debug interface) on EVK11xx
#define USB_PID_ATMEL_UC3_AUDIO_SPEAKER_MICRO 0x2311
#define USB_PID_ATMEL_UC3_CDC_MSC 0x2312
//! @}
//! \name The range 2400h to 24FFh is reserved to PIDs for ASF applications
//! @{
#define USB_PID_ATMEL_ASF_HIDMOUSE 0x2400
#define USB_PID_ATMEL_ASF_HIDKEYBOARD 0x2401
#define USB_PID_ATMEL_ASF_HIDGENERIC 0x2402
#define USB_PID_ATMEL_ASF_MSC 0x2403
#define USB_PID_ATMEL_ASF_CDC 0x2404
#define USB_PID_ATMEL_ASF_PHDC 0x2405
#define USB_PID_ATMEL_ASF_HIDMTOUCH 0x2406
#define USB_PID_ATMEL_ASF_MSC_HIDMOUSE 0x2420
#define USB_PID_ATMEL_ASF_MSC_HIDS_CDC 0x2421
#define USB_PID_ATMEL_ASF_MSC_HIDKEYBOARD 0x2422
#define USB_PID_ATMEL_ASF_VENDOR_CLASS 0x2423
#define USB_PID_ATMEL_ASF_MSC_CDC 0x2424
#define USB_PID_ATMEL_ASF_TWO_CDC 0x2425
#define USB_PID_ATMEL_ASF_SEVEN_CDC 0x2426
#define USB_PID_ATMEL_ASF_XPLAIN_BC_POWERONLY 0x2430
#define USB_PID_ATMEL_ASF_XPLAIN_BC_TERMINAL 0x2431
#define USB_PID_ATMEL_ASF_XPLAIN_BC_TOUCH 0x2432
#define USB_PID_ATMEL_ASF_AUDIO_SPEAKER 0x2433
#define USB_PID_ATMEL_ASF_XMEGA_B1_XPLAINED 0x2434
//! @}
//! \name The range 2F00h to 2FFFh is reserved to official PIDs for AVR bootloaders
//! Note, !!!! don't use this range for demos or examples !!!!
//! @{
#define USB_PID_ATMEL_DFU_ATXMEGA64C3 0x2FD6
#define USB_PID_ATMEL_DFU_ATXMEGA128C3 0x2FD7
#define USB_PID_ATMEL_DFU_ATXMEGA16C4 0x2FD8
#define USB_PID_ATMEL_DFU_ATXMEGA32C4 0x2FD9
#define USB_PID_ATMEL_DFU_ATXMEGA256C3 0x2FDA
#define USB_PID_ATMEL_DFU_ATXMEGA384C3 0x2FDB
#define USB_PID_ATMEL_DFU_ATUCL3_L4 0x2FDC
#define USB_PID_ATMEL_DFU_ATXMEGA64A4U 0x2FDD
#define USB_PID_ATMEL_DFU_ATXMEGA128A4U 0x2FDE
#define USB_PID_ATMEL_DFU_ATXMEGA64B3 0x2FDF
#define USB_PID_ATMEL_DFU_ATXMEGA128B3 0x2FE0
#define USB_PID_ATMEL_DFU_ATXMEGA64B1 0x2FE1
#define USB_PID_ATMEL_DFU_ATXMEGA256A3BU 0x2FE2
#define USB_PID_ATMEL_DFU_ATXMEGA16A4U 0x2FE3
#define USB_PID_ATMEL_DFU_ATXMEGA32A4U 0x2FE4
#define USB_PID_ATMEL_DFU_ATXMEGA64A3U 0x2FE5
#define USB_PID_ATMEL_DFU_ATXMEGA128A3U 0x2FE6
#define USB_PID_ATMEL_DFU_ATXMEGA192A3U 0x2FE7
#define USB_PID_ATMEL_DFU_ATXMEGA64A1U 0x2FE8
#define USB_PID_ATMEL_DFU_ATUC3D 0x2FE9
#define USB_PID_ATMEL_DFU_ATXMEGA128B1 0x2FEA
#define USB_PID_ATMEL_DFU_AT32UC3C 0x2FEB
#define USB_PID_ATMEL_DFU_ATXMEGA256A3U 0x2FEC
#define USB_PID_ATMEL_DFU_ATXMEGA128A1U 0x2FED
#define USB_PID_ATMEL_DFU_ATMEGA8U2 0x2FEE
#define USB_PID_ATMEL_DFU_ATMEGA16U2 0x2FEF
#define USB_PID_ATMEL_DFU_ATMEGA32U2 0x2FF0
#define USB_PID_ATMEL_DFU_AT32UC3A3 0x2FF1
#define USB_PID_ATMEL_DFU_ATMEGA32U6 0x2FF2
#define USB_PID_ATMEL_DFU_ATMEGA16U4 0x2FF3
#define USB_PID_ATMEL_DFU_ATMEGA32U4 0x2FF4
#define USB_PID_ATMEL_DFU_AT32AP7200 0x2FF5
#define USB_PID_ATMEL_DFU_AT32UC3B 0x2FF6
#define USB_PID_ATMEL_DFU_AT90USB82 0x2FF7
#define USB_PID_ATMEL_DFU_AT32UC3A 0x2FF8
#define USB_PID_ATMEL_DFU_AT90USB64 0x2FF9
#define USB_PID_ATMEL_DFU_AT90USB162 0x2FFA
#define USB_PID_ATMEL_DFU_AT90USB128 0x2FFB
// 2FFCh to 2FFFh used by C51 family products
//! @}
//! @}
//! @}
#endif // _USB_ATMEL_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,97 @@
/**
* \file
*
* \brief Declaration of main function used by HID keyboard example
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _MAIN_H_
#define _MAIN_H_
//Enters the application in low power mode
//Callback called when USB host sets USB line in suspend state
void main_suspend_action(void);
//Called by UDD when the USB line exit of suspend state
void main_resume_action(void);
//Called when a start of frame is received on USB line
void main_sof_action(void);
//Called by UDC when USB Host request to enable remote wakeup
void main_remotewakeup_enable(void);
//Called by UDC when USB Host request to disable remote wakeup
void main_remotewakeup_disable(void);
#ifdef KBD
extern volatile bool main_b_kbd_enable;
bool main_kbd_enable(void);
void main_kbd_disable(void);
#endif //KBD
#ifdef NKRO
extern volatile bool main_b_nkro_enable;
bool main_nkro_enable(void);
void main_nkro_disable(void);
#endif //NKRO
#ifdef EXK
extern volatile bool main_b_exk_enable;
bool main_exk_enable(void);
void main_exk_disable(void);
#endif //EXK
#ifdef MOU
extern volatile bool main_b_mou_enable;
bool main_mou_enable(void);
void main_mou_disable(void);
#endif //MOU
#ifdef RAW
extern volatile bool main_b_raw_enable;
bool main_raw_enable(void);
void main_raw_disable(void);
#endif //RAW
#endif // _MAIN_H_

View File

@ -0,0 +1,498 @@
/**
* \file
*
* \brief USB protocol definitions.
*
* This file contains the USB definitions and data structures provided by the
* USB 2.0 specification.
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _USB_PROTOCOL_H_
#define _USB_PROTOCOL_H_
#include "usb_atmel.h"
/**
* \ingroup usb_group
* \defgroup usb_protocol_group USB Protocol Definitions
*
* This module defines constants and data structures provided by the USB
* 2.0 specification.
*
* @{
*/
//! Value for field bcdUSB
#define USB_V2_0 0x0200 //!< USB Specification version 2.00
#define USB_V2_1 0x0201 //!< USB Specification version 2.01
/*! \name Generic definitions (Class, subclass and protocol)
*/
//! @{
#define NO_CLASS 0x00
#define CLASS_VENDOR_SPECIFIC 0xFF
#define NO_SUBCLASS 0x00
#define NO_PROTOCOL 0x00
//! @}
//! \name IAD (Interface Association Descriptor) constants
//! @{
#define CLASS_IAD 0xEF
#define SUB_CLASS_IAD 0x02
#define PROTOCOL_IAD 0x01
//! @}
/**
* \brief USB request data transfer direction (bmRequestType)
*/
#define USB_REQ_DIR_OUT (0<<7) //!< Host to device
#define USB_REQ_DIR_IN (1<<7) //!< Device to host
#define USB_REQ_DIR_MASK (1<<7) //!< Mask
/**
* \brief USB request types (bmRequestType)
*/
#define USB_REQ_TYPE_STANDARD (0<<5) //!< Standard request
#define USB_REQ_TYPE_CLASS (1<<5) //!< Class-specific request
#define USB_REQ_TYPE_VENDOR (2<<5) //!< Vendor-specific request
#define USB_REQ_TYPE_MASK (3<<5) //!< Mask
/**
* \brief USB recipient codes (bmRequestType)
*/
#define USB_REQ_RECIP_DEVICE (0<<0) //!< Recipient device
#define USB_REQ_RECIP_INTERFACE (1<<0) //!< Recipient interface
#define USB_REQ_RECIP_ENDPOINT (2<<0) //!< Recipient endpoint
#define USB_REQ_RECIP_OTHER (3<<0) //!< Recipient other
#define USB_REQ_RECIP_MASK (0x1F) //!< Mask
/**
* \brief Standard USB requests (bRequest)
*/
enum usb_reqid {
USB_REQ_GET_STATUS = 0,
USB_REQ_CLEAR_FEATURE = 1,
USB_REQ_SET_FEATURE = 3,
USB_REQ_SET_ADDRESS = 5,
USB_REQ_GET_DESCRIPTOR = 6,
USB_REQ_SET_DESCRIPTOR = 7,
USB_REQ_GET_CONFIGURATION = 8,
USB_REQ_SET_CONFIGURATION = 9,
USB_REQ_GET_INTERFACE = 10,
USB_REQ_SET_INTERFACE = 11,
USB_REQ_SYNCH_FRAME = 12,
};
/**
* \brief Standard USB device status flags
*
*/
enum usb_device_status {
USB_DEV_STATUS_BUS_POWERED = 0,
USB_DEV_STATUS_SELF_POWERED = 1,
USB_DEV_STATUS_REMOTEWAKEUP = 2
};
/**
* \brief Standard USB Interface status flags
*
*/
enum usb_interface_status {
USB_IFACE_STATUS_RESERVED = 0
};
/**
* \brief Standard USB endpoint status flags
*
*/
enum usb_endpoint_status {
USB_EP_STATUS_HALTED = 1,
};
/**
* \brief Standard USB device feature flags
*
* \note valid for SetFeature request.
*/
enum usb_device_feature {
USB_DEV_FEATURE_REMOTE_WAKEUP = 1, //!< Remote wakeup enabled
USB_DEV_FEATURE_TEST_MODE = 2, //!< USB test mode
USB_DEV_FEATURE_OTG_B_HNP_ENABLE = 3,
USB_DEV_FEATURE_OTG_A_HNP_SUPPORT = 4,
USB_DEV_FEATURE_OTG_A_ALT_HNP_SUPPORT = 5
};
/**
* \brief Test Mode possible on HS USB device
*
* \note valid for USB_DEV_FEATURE_TEST_MODE request.
*/
enum usb_device_hs_test_mode {
USB_DEV_TEST_MODE_J = 1,
USB_DEV_TEST_MODE_K = 2,
USB_DEV_TEST_MODE_SE0_NAK = 3,
USB_DEV_TEST_MODE_PACKET = 4,
USB_DEV_TEST_MODE_FORCE_ENABLE = 5,
};
/**
* \brief Standard USB endpoint feature/status flags
*/
enum usb_endpoint_feature {
USB_EP_FEATURE_HALT = 0,
};
/**
* \brief Standard USB Test Mode Selectors
*/
enum usb_test_mode_selector {
USB_TEST_J = 0x01,
USB_TEST_K = 0x02,
USB_TEST_SE0_NAK = 0x03,
USB_TEST_PACKET = 0x04,
USB_TEST_FORCE_ENABLE = 0x05,
};
/**
* \brief Standard USB descriptor types
*/
enum usb_descriptor_type {
USB_DT_DEVICE = 1,
USB_DT_CONFIGURATION = 2,
USB_DT_STRING = 3,
USB_DT_INTERFACE = 4,
USB_DT_ENDPOINT = 5,
USB_DT_DEVICE_QUALIFIER = 6,
USB_DT_OTHER_SPEED_CONFIGURATION = 7,
USB_DT_INTERFACE_POWER = 8,
USB_DT_OTG = 9,
USB_DT_IAD = 0x0B,
USB_DT_BOS = 0x0F,
USB_DT_DEVICE_CAPABILITY = 0x10,
};
/**
* \brief USB Device Capability types
*/
enum usb_capability_type {
USB_DC_USB20_EXTENSION = 0x02,
};
/**
* \brief USB Device Capability - USB 2.0 Extension
* To fill bmAttributes field of usb_capa_ext_desc_t structure.
*/
enum usb_capability_extension_attr {
USB_DC_EXT_LPM = 0x00000002,
};
#define HIRD_50_US 0
#define HIRD_125_US 1
#define HIRD_200_US 2
#define HIRD_275_US 3
#define HIRD_350_US 4
#define HIRD_425_US 5
#define HIRD_500_US 6
#define HIRD_575_US 7
#define HIRD_650_US 8
#define HIRD_725_US 9
#define HIRD_800_US 10
#define HIRD_875_US 11
#define HIRD_950_US 12
#define HIRD_1025_US 13
#define HIRD_1100_US 14
#define HIRD_1175_US 15
/** Fields definition from a LPM TOKEN */
#define USB_LPM_ATTRIBUT_BLINKSTATE_MASK (0xF << 0)
#define USB_LPM_ATTRIBUT_FIRD_MASK (0xF << 4)
#define USB_LPM_ATTRIBUT_REMOTEWAKE_MASK (1 << 8)
#define USB_LPM_ATTRIBUT_BLINKSTATE(value) ((value & 0xF) << 0)
#define USB_LPM_ATTRIBUT_FIRD(value) ((value & 0xF) << 4)
#define USB_LPM_ATTRIBUT_REMOTEWAKE(value) ((value & 1) << 8)
#define USB_LPM_ATTRIBUT_BLINKSTATE_L1 USB_LPM_ATTRIBUT_BLINKSTATE(1)
/**
* \brief Standard USB endpoint transfer types
*/
enum usb_ep_type {
USB_EP_TYPE_CONTROL = 0x00,
USB_EP_TYPE_ISOCHRONOUS = 0x01,
USB_EP_TYPE_BULK = 0x02,
USB_EP_TYPE_INTERRUPT = 0x03,
USB_EP_TYPE_MASK = 0x03,
};
/**
* \brief Standard USB language IDs for string descriptors
*/
enum usb_langid {
USB_LANGID_EN_US = 0x0409, //!< English (United States)
};
/**
* \brief Mask selecting the index part of an endpoint address
*/
#define USB_EP_ADDR_MASK 0x0f
//! \brief USB address identifier
typedef uint8_t usb_add_t;
/**
* \brief Endpoint transfer direction is IN
*/
#define USB_EP_DIR_IN 0x80
/**
* \brief Endpoint transfer direction is OUT
*/
#define USB_EP_DIR_OUT 0x00
//! \brief Endpoint identifier
typedef uint8_t usb_ep_t;
/**
* \brief Maximum length in bytes of a USB descriptor
*
* The maximum length of a USB descriptor is limited by the 8-bit
* bLength field.
*/
#define USB_MAX_DESC_LEN 255
/*
* 2-byte alignment requested for all USB structures.
*/
COMPILER_PACK_SET(1)
/**
* \brief A USB Device SETUP request
*
* The data payload of SETUP packets always follows this structure.
*/
typedef struct {
uint8_t bmRequestType;
uint8_t bRequest;
le16_t wValue;
le16_t wIndex;
le16_t wLength;
} usb_setup_req_t;
/**
* \brief Standard USB device descriptor structure
*/
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
le16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
le16_t idVendor;
le16_t idProduct;
le16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} usb_dev_desc_t;
/**
* \brief Standard USB device qualifier descriptor structure
*
* This descriptor contains information about the device when running at
* the "other" speed (i.e. if the device is currently operating at high
* speed, this descriptor can be used to determine what would change if
* the device was operating at full speed.)
*/
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
le16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
uint8_t bReserved;
} usb_dev_qual_desc_t;
/**
* \brief USB Device BOS descriptor structure
*
* The BOS descriptor (Binary device Object Store) defines a root
* descriptor that is similar to the configuration descriptor, and is
* the base descriptor for accessing a family of related descriptors.
* A host can read a BOS descriptor and learn from the wTotalLength field
* the entire size of the device-level descriptor set, or it can read in
* the entire BOS descriptor set of device capabilities.
* The host accesses this descriptor using the GetDescriptor() request.
* The descriptor type in the GetDescriptor() request is set to BOS.
*/
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
le16_t wTotalLength;
uint8_t bNumDeviceCaps;
} usb_dev_bos_desc_t;
/**
* \brief USB Device Capabilities - USB 2.0 Extension Descriptor structure
*
* Defines the set of USB 1.1-specific device level capabilities.
*/
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
le32_t bmAttributes;
} usb_dev_capa_ext_desc_t;
/**
* \brief USB Device LPM Descriptor structure
*
* The BOS descriptor and capabilities descriptors for LPM.
*/
typedef struct {
usb_dev_bos_desc_t bos;
usb_dev_capa_ext_desc_t capa_ext;
} usb_dev_lpm_desc_t;
/**
* \brief Standard USB Interface Association Descriptor structure
*/
typedef struct {
uint8_t bLength; //!< size of this descriptor in bytes
uint8_t bDescriptorType; //!< INTERFACE descriptor type
uint8_t bFirstInterface; //!< Number of interface
uint8_t bInterfaceCount; //!< value to select alternate setting
uint8_t bFunctionClass; //!< Class code assigned by the USB
uint8_t bFunctionSubClass;//!< Sub-class code assigned by the USB
uint8_t bFunctionProtocol;//!< Protocol code assigned by the USB
uint8_t iFunction; //!< Index of string descriptor
} usb_association_desc_t;
/**
* \brief Standard USB configuration descriptor structure
*/
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
le16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} usb_conf_desc_t;
#define USB_CONFIG_ATTR_MUST_SET (1 << 7) //!< Must always be set
#define USB_CONFIG_ATTR_BUS_POWERED (0 << 6) //!< Bus-powered
#define USB_CONFIG_ATTR_SELF_POWERED (1 << 6) //!< Self-powered
#define USB_CONFIG_ATTR_REMOTE_WAKEUP (1 << 5) //!< remote wakeup supported
#define USB_CONFIG_MAX_POWER(ma) (((ma) + 1) / 2) //!< Max power in mA
/**
* \brief Standard USB association descriptor structure
*/
typedef struct {
uint8_t bLength; //!< Size of this descriptor in bytes
uint8_t bDescriptorType; //!< Interface descriptor type
uint8_t bFirstInterface; //!< Number of interface
uint8_t bInterfaceCount; //!< value to select alternate setting
uint8_t bFunctionClass; //!< Class code assigned by the USB
uint8_t bFunctionSubClass; //!< Sub-class code assigned by the USB
uint8_t bFunctionProtocol; //!< Protocol code assigned by the USB
uint8_t iFunction; //!< Index of string descriptor
} usb_iad_desc_t;
/**
* \brief Standard USB interface descriptor structure
*/
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} usb_iface_desc_t;
/**
* \brief Standard USB endpoint descriptor structure
*/
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
le16_t wMaxPacketSize;
uint8_t bInterval;
} usb_ep_desc_t;
/**
* \brief A standard USB string descriptor structure
*/
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
} usb_str_desc_t;
typedef struct {
usb_str_desc_t desc;
le16_t string[1];
} usb_str_lgid_desc_t;
COMPILER_PACK_RESET()
//! @}
#endif /* _USB_PROTOCOL_H_ */

View File

@ -0,0 +1,193 @@
/**
* \file
*
* \brief USB Communication Device Class (CDC) protocol definitions
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _USB_PROTOCOL_CDC_H_
#define _USB_PROTOCOL_CDC_H_
#include "compiler.h"
#ifdef CDC
#define CDC_CLASS_DEVICE 0x02 //!< USB Communication Device Class
#define CDC_CLASS_COMM 0x02 //!< CDC Communication Class Interface
#define CDC_CLASS_DATA 0x0A //!< CDC Data Class Interface
#define CDC_SUBCLASS_DLCM 0x01 //!< Direct Line Control Model
#define CDC_SUBCLASS_ACM 0x02 //!< Abstract Control Model
#define CDC_SUBCLASS_TCM 0x03 //!< Telephone Control Model
#define CDC_SUBCLASS_MCCM 0x04 //!< Multi-Channel Control Model
#define CDC_SUBCLASS_CCM 0x05 //!< CAPI Control Model
#define CDC_SUBCLASS_ETH 0x06 //!< Ethernet Networking Control Model
#define CDC_SUBCLASS_ATM 0x07 //!< ATM Networking Control Model
#define CDC_PROTOCOL_V25TER 0x01 //!< Common AT commands
#define CDC_PROTOCOL_I430 0x30 //!< ISDN BRI
#define CDC_PROTOCOL_HDLC 0x31 //!< HDLC
#define CDC_PROTOCOL_TRANS 0x32 //!< Transparent
#define CDC_PROTOCOL_Q921M 0x50 //!< Q.921 management protocol
#define CDC_PROTOCOL_Q921 0x51 //!< Q.931 [sic] Data link protocol
#define CDC_PROTOCOL_Q921TM 0x52 //!< Q.921 TEI-multiplexor
#define CDC_PROTOCOL_V42BIS 0x90 //!< Data compression procedures
#define CDC_PROTOCOL_Q931 0x91 //!< Euro-ISDN protocol control
#define CDC_PROTOCOL_V120 0x92 //!< V.24 rate adaption to ISDN
#define CDC_PROTOCOL_CAPI20 0x93 //!< CAPI Commands
#define CDC_PROTOCOL_HOST 0xFD //!< Host based driver
#define CDC_PROTOCOL_PUFD 0xFE
#define CDC_CS_INTERFACE 0x24 //!< Interface Functional Descriptor
#define CDC_CS_ENDPOINT 0x25 //!< Endpoint Functional Descriptor
#define CDC_SCS_HEADER 0x00 //!< Header Functional Descriptor
#define CDC_SCS_CALL_MGMT 0x01 //!< Call Management
#define CDC_SCS_ACM 0x02 //!< Abstract Control Management
#define CDC_SCS_UNION 0x06 //!< Union Functional Descriptor
#define USB_REQ_CDC_SEND_ENCAPSULATED_COMMAND 0x00
#define USB_REQ_CDC_GET_ENCAPSULATED_RESPONSE 0x01
#define USB_REQ_CDC_SET_COMM_FEATURE 0x02
#define USB_REQ_CDC_GET_COMM_FEATURE 0x03
#define USB_REQ_CDC_CLEAR_COMM_FEATURE 0x04
#define USB_REQ_CDC_SET_AUX_LINE_STATE 0x10
#define USB_REQ_CDC_SET_HOOK_STATE 0x11
#define USB_REQ_CDC_PULSE_SETUP 0x12
#define USB_REQ_CDC_SEND_PULSE 0x13
#define USB_REQ_CDC_SET_PULSE_TIME 0x14
#define USB_REQ_CDC_RING_AUX_JACK 0x15
#define USB_REQ_CDC_SET_LINE_CODING 0x20
#define USB_REQ_CDC_GET_LINE_CODING 0x21
#define USB_REQ_CDC_SET_CONTROL_LINE_STATE 0x22
#define USB_REQ_CDC_SEND_BREAK 0x23
#define USB_REQ_CDC_SET_RINGER_PARMS 0x30
#define USB_REQ_CDC_GET_RINGER_PARMS 0x31
#define USB_REQ_CDC_SET_OPERATION_PARMS 0x32
#define USB_REQ_CDC_GET_OPERATION_PARMS 0x33
#define USB_REQ_CDC_SET_LINE_PARMS 0x34
#define USB_REQ_CDC_GET_LINE_PARMS 0x35
#define USB_REQ_CDC_DIAL_DIGITS 0x36
#define USB_REQ_CDC_SET_UNIT_PARAMETER 0x37
#define USB_REQ_CDC_GET_UNIT_PARAMETER 0x38
#define USB_REQ_CDC_CLEAR_UNIT_PARAMETER 0x39
#define USB_REQ_CDC_GET_PROFILE 0x3A
#define USB_REQ_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
#define USB_REQ_CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x41
#define USB_REQ_CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x42
#define USB_REQ_CDC_SET_ETHERNET_PACKET_FILTER 0x43
#define USB_REQ_CDC_GET_ETHERNET_STATISTIC 0x44
#define USB_REQ_CDC_SET_ATM_DATA_FORMAT 0x50
#define USB_REQ_CDC_GET_ATM_DEVICE_STATISTICS 0x51
#define USB_REQ_CDC_SET_ATM_DEFAULT_VC 0x52
#define USB_REQ_CDC_GET_ATM_VC_STATISTICS 0x53
// Added bNotification codes according cdc spec 1.1 chapter 6.3
#define USB_REQ_CDC_NOTIFY_RING_DETECT 0x09
#define USB_REQ_CDC_NOTIFY_SERIAL_STATE 0x20
#define USB_REQ_CDC_NOTIFY_CALL_STATE_CHANGE 0x28
#define USB_REQ_CDC_NOTIFY_LINE_STATE_CHANGE 0x29
#define CDC_CALL_MGMT_SUPPORTED (1 << 0)
#define CDC_CALL_MGMT_OVER_DCI (1 << 1)
#define CDC_ACM_SUPPORT_FEATURE_REQUESTS (1 << 0)
#define CDC_ACM_SUPPORT_LINE_REQUESTS (1 << 1)
#define CDC_ACM_SUPPORT_SENDBREAK_REQUESTS (1 << 2)
#define CDC_ACM_SUPPORT_NOTIFY_REQUESTS (1 << 3)
#pragma pack(push,1)
typedef struct {
le32_t dwDTERate;
uint8_t bCharFormat;
uint8_t bParityType;
uint8_t bDataBits;
} usb_cdc_line_coding_t;
#pragma pack(pop)
enum cdc_char_format {
CDC_STOP_BITS_1 = 0, //!< 1 stop bit
CDC_STOP_BITS_1_5 = 1, //!< 1.5 stop bits
CDC_STOP_BITS_2 = 2, //!< 2 stop bits
};
enum cdc_parity {
CDC_PAR_NONE = 0, //!< No parity
CDC_PAR_ODD = 1, //!< Odd parity
CDC_PAR_EVEN = 2, //!< Even parity
CDC_PAR_MARK = 3, //!< Parity forced to 0 (space)
CDC_PAR_SPACE = 4, //!< Parity forced to 1 (mark)
};
typedef struct {
uint16_t value;
} usb_cdc_control_signal_t;
#define CDC_CTRL_SIGNAL_ACTIVATE_CARRIER (1 << 1)
#define CDC_CTRL_SIGNAL_DTE_PRESENT (1 << 0)
typedef struct {
uint8_t bmRequestType;
uint8_t bNotification;
le16_t wValue;
le16_t wIndex;
le16_t wLength;
} usb_cdc_notify_msg_t;
typedef struct {
usb_cdc_notify_msg_t header;
le16_t value;
} usb_cdc_notify_serial_state_t;
#define CDC_SERIAL_STATE_DCD CPU_TO_LE16((1<<0))
#define CDC_SERIAL_STATE_DSR CPU_TO_LE16((1<<1))
#define CDC_SERIAL_STATE_BREAK CPU_TO_LE16((1<<2))
#define CDC_SERIAL_STATE_RING CPU_TO_LE16((1<<3))
#define CDC_SERIAL_STATE_FRAMING CPU_TO_LE16((1<<4))
#define CDC_SERIAL_STATE_PARITY CPU_TO_LE16((1<<5))
#define CDC_SERIAL_STATE_OVERRUN CPU_TO_LE16((1<<6))
#endif
#endif // _USB_PROTOCOL_CDC_H_

View File

@ -0,0 +1,319 @@
/**
* \file
*
* \brief USB Human Interface Device (HID) protocol definitions.
*
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef _USB_PROTOCOL_HID_H_
#define _USB_PROTOCOL_HID_H_
/**
* \ingroup usb_protocol_group
* \defgroup usb_hid_protocol USB Human Interface Device (HID)
* protocol definitions
* \brief USB Human Interface Device (HID) protocol definitions
*
* @{
*/
//! \name Possible Class value
//@{
#define HID_CLASS 0x03
//@}
//! \name Possible SubClass value
//@{
//! Interface subclass NO support BOOT protocol
#define HID_SUB_CLASS_NOBOOT 0x00
//! Interface subclass support BOOT protocol
#define HID_SUB_CLASS_BOOT 0x01
//@}
//! \name Possible protocol value
//@{
//! Protocol generic standard
#define HID_PROTOCOL_GENERIC 0x00
//! Protocol keyboard standard
#define HID_PROTOCOL_KEYBOARD 0x01
//! Protocol mouse standard
#define HID_PROTOCOL_MOUSE 0x02
//@}
//! \brief Hid USB requests (bRequest)
enum usb_reqid_hid {
USB_REQ_HID_GET_REPORT = 0x01,
USB_REQ_HID_GET_IDLE = 0x02,
USB_REQ_HID_GET_PROTOCOL = 0x03,
USB_REQ_HID_SET_REPORT = 0x09,
USB_REQ_HID_SET_IDLE = 0x0A,
USB_REQ_HID_SET_PROTOCOL = 0x0B,
};
//! \brief HID USB descriptor types
enum usb_descriptor_type_hid {
USB_DT_HID = 0x21,
USB_DT_HID_REPORT = 0x22,
USB_DT_HID_PHYSICAL = 0x23,
};
//! \brief HID Type for report descriptor
enum usb_hid_item_report_type {
USB_HID_ITEM_REPORT_TYPE_MAIN = 0,
USB_HID_ITEM_REPORT_TYPE_GLOBAL = 1,
USB_HID_ITEM_REPORT_TYPE_LOCAL = 2,
USB_HID_ITEM_REPORT_TYPE_LONG = 3,
};
//! \brief HID report type
enum usb_hid_report_type {
USB_HID_REPORT_TYPE_INPUT = 1,
USB_HID_REPORT_TYPE_OUTPUT = 2,
USB_HID_REPORT_TYPE_FEATURE = 3,
};
//! \brief HID protocol
enum usb_hid_protocol {
USB_HID_PROCOTOL_BOOT = 0,
USB_HID_PROCOTOL_REPORT = 1,
};
COMPILER_PACK_SET(1)
//! \brief HID Descriptor
typedef struct {
uint8_t bLength; //!< Size of this descriptor in bytes
uint8_t bDescriptorType; //!< HID descriptor type
le16_t bcdHID; //!< Binary Coded Decimal Spec. release
uint8_t bCountryCode; //!< Hardware target country
uint8_t bNumDescriptors; //!< Number of HID class descriptors to follow
uint8_t bRDescriptorType; //!< Report descriptor type
le16_t wDescriptorLength; //!< Total length of Report descriptor
} usb_hid_descriptor_t;
COMPILER_PACK_RESET()
//! \name HID Report type
//! Used by SETUP_HID_GET_REPORT & SETUP_HID_SET_REPORT
//! @{
#define REPORT_TYPE_INPUT 0x01
#define REPORT_TYPE_OUTPUT 0x02
#define REPORT_TYPE_FEATURE 0x03
//! @}
//! \name Constants of field DESCRIPTOR_HID
//! @{
//! Numeric expression identifying the HID Class
//! Specification release (here V1.11)
#define USB_HID_BDC_V1_11 0x0111
//! Numeric expression specifying the number of class descriptors
//! Note: Always at least one i.e. Report descriptor.
#define USB_HID_NUM_DESC 0x01
//! \name Country code
//! @{
#define USB_HID_NO_COUNTRY_CODE 0 // Not Supported
#define USB_HID_COUNTRY_ARABIC 1 // Arabic
#define USB_HID_COUNTRY_BELGIAN 2 // Belgian
#define USB_HID_COUNTRY_CANADIAN_BILINGUAL 3 // Canadian-Bilingual
#define USB_HID_COUNTRY_CANADIAN_FRENCH 4 // Canadian-French
#define USB_HID_COUNTRY_CZECH_REPUBLIC 5 // Czech Republic
#define USB_HID_COUNTRY_DANISH 6 // Danish
#define USB_HID_COUNTRY_FINNISH 7 // Finnish
#define USB_HID_COUNTRY_FRENCH 8 // French
#define USB_HID_COUNTRY_GERMAN 9 // German
#define USB_HID_COUNTRY_GREEK 10 // Greek
#define USB_HID_COUNTRY_HEBREW 11 // Hebrew
#define USB_HID_COUNTRY_HUNGARY 12 // Hungary
#define USB_HID_COUNTRY_INTERNATIONAL_ISO 13 // International (ISO)
#define USB_HID_COUNTRY_ITALIAN 14 // Italian
#define USB_HID_COUNTRY_JAPAN_KATAKANA 15 // Japan (Katakana)
#define USB_HID_COUNTRY_KOREAN 16 // Korean
#define USB_HID_COUNTRY_LATIN_AMERICAN 17 // Latin American
#define USB_HID_COUNTRY_NETHERLANDS_DUTCH 18 // Netherlands/Dutch
#define USB_HID_COUNTRY_NORWEGIAN 19 // Norwegian
#define USB_HID_COUNTRY_PERSIAN_FARSI 20 // Persian (Farsi)
#define USB_HID_COUNTRY_POLAND 21 // Poland
#define USB_HID_COUNTRY_PORTUGUESE 22 // Portuguese
#define USB_HID_COUNTRY_RUSSIA 23 // Russia
#define USB_HID_COUNTRY_SLOVAKIA 24 // Slovakia
#define USB_HID_COUNTRY_SPANISH 25 // Spanish
#define USB_HID_COUNTRY_SWEDISH 26 // Swedish
#define USB_HID_COUNTRY_SWISS_FRENCH 27 // Swiss/French
#define USB_HID_COUNTRY_SWISS_GERMAN 28 // Swiss/German
#define USB_HID_COUNTRY_SWITZERLAND 29 // Switzerland
#define USB_HID_COUNTRY_TAIWAN 30 // Taiwan
#define USB_HID_COUNTRY_TURKISH_Q 31 // Turkish-Q
#define USB_HID_COUNTRY_UK 32 // UK
#define USB_HID_COUNTRY_US 33 // US
#define USB_HID_COUNTRY_YUGOSLAVIA 34 // Yugoslavia
#define USB_HID_COUNTRY_TURKISH_F 35 // Turkish-F
//! @}
//! @}
//! @}
//! \name HID KEYS values
//! @{
#define HID_A 0x04
#define HID_B 0x05
#define HID_C 0x06
#define HID_D 0x07
#define HID_E 0x08
#define HID_F 0x09
#define HID_G 0x0A
#define HID_H 0x0B
#define HID_I 0x0C
#define HID_J 0x0D
#define HID_K 0x0E
#define HID_L 0x0F
#define HID_M 0x10
#define HID_N 0x11
#define HID_O 0x12
#define HID_P 0x13
#define HID_Q 0x14
#define HID_R 0x15
#define HID_S 0x16
#define HID_T 0x17
#define HID_U 0x18
#define HID_V 0x19
#define HID_W 0x1A
#define HID_X 0x1B
#define HID_Y 0x1C
#define HID_Z 0x1D
#define HID_1 30
#define HID_2 31
#define HID_3 32
#define HID_4 33
#define HID_5 34
#define HID_6 35
#define HID_7 36
#define HID_8 37
#define HID_9 38
#define HID_0 39
#define HID_ENTER 40
#define HID_ESCAPE 41
#define HID_BACKSPACE 42
#define HID_TAB 43
#define HID_SPACEBAR 44
#define HID_UNDERSCORE 45
#define HID_PLUS 46
#define HID_OPEN_BRACKET 47 // {
#define HID_CLOSE_BRACKET 48 // }
#define HID_BACKSLASH 49
#define HID_ASH 50 // # ~
#define HID_COLON 51 // ; :
#define HID_QUOTE 52 // ' "
#define HID_TILDE 53
#define HID_COMMA 54
#define HID_DOT 55
#define HID_SLASH 56
#define HID_CAPS_LOCK 57
#define HID_F1 58
#define HID_F2 59
#define HID_F3 60
#define HID_F4 61
#define HID_F5 62
#define HID_F6 63
#define HID_F7 64
#define HID_F8 65
#define HID_F9 66
#define HID_F10 67
#define HID_F11 68
#define HID_F12 69
#define HID_PRINTSCREEN 70
#define HID_SCROLL_LOCK 71
#define HID_PAUSE 72
#define HID_INSERT 73
#define HID_HOME 74
#define HID_PAGEUP 75
#define HID_DELETE 76
#define HID_END 77
#define HID_PAGEDOWN 78
#define HID_RIGHT 79
#define HID_LEFT 80
#define HID_DOWN 81
#define HID_UP 82
#define HID_KEYPAD_NUM_LOCK 83
#define HID_KEYPAD_DIVIDE 84
#define HID_KEYPAD_AT 85
#define HID_KEYPAD_MULTIPLY 85
#define HID_KEYPAD_MINUS 86
#define HID_KEYPAD_PLUS 87
#define HID_KEYPAD_ENTER 88
#define HID_KEYPAD_1 89
#define HID_KEYPAD_2 90
#define HID_KEYPAD_3 91
#define HID_KEYPAD_4 92
#define HID_KEYPAD_5 93
#define HID_KEYPAD_6 94
#define HID_KEYPAD_7 95
#define HID_KEYPAD_8 96
#define HID_KEYPAD_9 97
#define HID_KEYPAD_0 98
//! \name HID modifier values
//! @{
#define HID_MODIFIER_NONE 0x00
#define HID_MODIFIER_LEFT_CTRL 0x01
#define HID_MODIFIER_LEFT_SHIFT 0x02
#define HID_MODIFIER_LEFT_ALT 0x04
#define HID_MODIFIER_LEFT_UI 0x08
#define HID_MODIFIER_RIGHT_CTRL 0x10
#define HID_MODIFIER_RIGHT_SHIFT 0x20
#define HID_MODIFIER_RIGHT_ALT 0x40
#define HID_MODIFIER_RIGHT_UI 0x80
//! @}
//! @}
//! \name HID KEYS values
//! @{
#define HID_LED_NUM_LOCK (1<<0)
#define HID_LED_CAPS_LOCK (1<<1)
#define HID_LED_SCROLL_LOCK (1<<2)
#define HID_LED_COMPOSE (1<<3)
#define HID_LED_KANA (1<<4)
//! @}
#endif // _USB_PROTOCOL_HID_H_

View File

@ -0,0 +1,59 @@
#include "samd51j18a.h"
#include "string.h"
#include "usb_util.h"
char digit(int d, int radix)
{
if (d < 10)
{
return d + '0';
}
else
{
return d - 10 + 'A';
}
}
int UTIL_ltoa_radix(int64_t value, char *dest, int radix)
{
int64_t original = value; //save original value
char buf[25] = "";
int c = sizeof(buf)-1;
int last = c;
int d;
int size;
if (value < 0) //if it's negative, take the absolute value
value = -value;
do //write least significant digit of value that's left
{
d = (value % radix);
buf[--c] = digit(d, radix);
value /= radix;
} while (value);
if (original < 0)
buf[--c] = '-';
size = last - c + 1; //includes null at end
memcpy(dest, &buf[c], last - c + 1);
return (size - 1); //without null termination
}
int UTIL_ltoa(int64_t value, char *dest)
{
return UTIL_ltoa_radix(value, dest, 10);
}
int UTIL_itoa(int value, char *dest)
{
return UTIL_ltoa_radix((int64_t)value, dest, 10);
}
int UTIL_utoa(uint32_t value, char *dest)
{
return UTIL_ltoa_radix((int64_t)value, dest, 10);
}

View File

@ -0,0 +1,10 @@
#ifndef _USB_UTIL_H_
#define _USB_UTIL_H_
int UTIL_ltoa_radix(int64_t value, char *dest, int radix);
int UTIL_ltoa(int64_t value, char *dest);
int UTIL_itoa(int value, char *dest);
int UTIL_utoa(uint32_t value, char *dest);
#endif //_USB_UTIL_H_

View File

@ -0,0 +1,8 @@
#ifndef _wait_api_h_
#define _wait_api_h_
void wait_ms(uint64_t msec);
void wait_us(uint16_t usec);
#endif