Example #1
0
//-----------------------------------------------------------------------------
static void uart_init(uint32_t baud)
{
  uint64_t br = (uint64_t)65536 * (F_CPU - 16 * baud) / F_CPU;

  HAL_GPIO_UART_TX_out();
  HAL_GPIO_UART_TX_pmuxen(PORT_PMUX_PMUXE_C_Val);
  HAL_GPIO_UART_RX_in();
  HAL_GPIO_UART_RX_pmuxen(PORT_PMUX_PMUXE_C_Val);

  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM0_GCLK_ID_CORE) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

  SERCOM0->USART.CTRLA.reg =
      SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK |
      SERCOM_USART_CTRLA_RXPO(3/*PAD3*/) | SERCOM_USART_CTRLA_TXPO(1/*PAD2*/);

  SERCOM0->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN |
      SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/);

  SERCOM0->USART.BAUD.reg = (uint16_t)br+1;

  SERCOM0->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;
}
Example #2
0
/*
This is a slightly modified version of the timer setup found at:
https://github.com/maxbader/arduino_tools
 */
void startTimer(int frequencyHz) {
  REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID (GCM_TCC2_TC3)) ;
  while ( GCLK->STATUS.bit.SYNCBUSY == 1 );

  TcCount16* TC = (TcCount16*) TC3;

  TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;

  // Use the 16-bit timer
  TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
  while (TC->STATUS.bit.SYNCBUSY == 1);

  // Use match mode so that the timer counter resets when the count matches the compare register
  TC->CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
  while (TC->STATUS.bit.SYNCBUSY == 1);

  // Set prescaler to 1024
  TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1024;
  while (TC->STATUS.bit.SYNCBUSY == 1);

  setTimerFrequency(frequencyHz);

  // Enable the compare interrupt
  TC->INTENSET.reg = 0;
  TC->INTENSET.bit.MC0 = 1;

  NVIC_EnableIRQ(TC3_IRQn);

  TC->CTRLA.reg |= TC_CTRLA_ENABLE;
  while (TC->STATUS.bit.SYNCBUSY == 1);
}
Example #3
0
/**
 * Configures the TC to generate output events at the sample frequency.
 *
 * Configures the TC in Frequency Generation mode, with an event output once
 * each time the audio sample frequency period expires.
 */
 void ZerodioClass::tcConfigure(uint32_t sampleRate)
{
	// Enable GCLK for TCC2 and TC5 (timer counter input clock)
	GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)) ;
	while (GCLK->STATUS.bit.SYNCBUSY);

	tcReset();

	// Set Timer counter Mode to 16 bits
	TC5->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16;

	// Set TC5 mode as match frequency
	TC5->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;

	TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1 | TC_CTRLA_ENABLE;

	TC5->COUNT16.CC[0].reg = (uint16_t) (SystemCoreClock / sampleRate - 1);
	while (tcIsSyncing());
	
	// Configure interrupt request
	NVIC_DisableIRQ(TC5_IRQn);
	NVIC_ClearPendingIRQ(TC5_IRQn);
	NVIC_SetPriority(TC5_IRQn, 0);
	NVIC_EnableIRQ(TC5_IRQn);

	// Enable the TC5 interrupt request
	TC5->COUNT16.INTENSET.bit.MC0 = 1;
	while (tcIsSyncing());
}	
Example #4
0
/*************************************************************************//**
*****************************************************************************/
void HAL_TimerInit(void)
{
	halTimerIrqCount = 0;

	PM->APBCMASK.reg					|= PM_APBCMASK_TC4;
	GCLK->CLKCTRL.reg					= GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_ID(0x15/*TC4,TC5*/) | GCLK_CLKCTRL_GEN(0);

	SYSTIMER.CTRLA.reg					= TC_CTRLA_MODE(TC_CTRLA_MODE_COUNT16_Val)
										| TC_CTRLA_WAVEGEN(TC_CTRLA_WAVEGEN_MFRQ_Val)
										| TC_CTRLA_PRESCALER(3 /*DIV8*/)
										| TC_CTRLA_PRESCSYNC(TC_CTRLA_PRESCSYNC_PRESC_Val);
	halTimerSync();

	SYSTIMER.COUNT.reg					= 0;
	halTimerSync();

	SYSTIMER.CC[0].reg					= TIMER_TOP;
	halTimerSync();

	SYSTIMER.CTRLA.reg					= TC_CTRLA_ENABLE;
	halTimerSync();

	SYSTIMER.INTENSET.reg				= TC_INTENSET_MC(0);
	NVIC_EnableIRQ(TC4_IRQn);
}
Example #5
0
void RtcInit() {
//     SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_ENABLE | SYSCTRL_XOSC32K_EN32K;
//     //wait for crystal to warm up
//     while((SYSCTRL->PCLKSR.reg & (SYSCTRL_PCLKSR_XOSC32KRDY)) == 0);

    GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) |
                       GCLK_GENDIV_DIV(8);

    GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) |
                        GCLK_GENCTRL_SRC(GCLK_SOURCE_OSC8M) |
                        GCLK_GENCTRL_IDC |
                        GCLK_GENCTRL_RUNSTDBY |
                        GCLK_GENCTRL_GENEN;
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
    // Configure RTC
    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(RTC_GCLK_ID) |
                        GCLK_CLKCTRL_CLKEN |
                        GCLK_CLKCTRL_GEN(2);

    RTC->MODE1.CTRL.reg = RTC_MODE1_CTRL_MODE_COUNT16;
    while (RTC->MODE1.STATUS.bit.SYNCBUSY);
    // Prescaler needs to be enabled separately from the mode for some reason
    RTC->MODE1.CTRL.reg |= RTC_MODE1_CTRL_PRESCALER_DIV1;
    while (RTC->MODE1.STATUS.bit.SYNCBUSY);
    RTC->MODE1.PER.reg = 998;
    while (RTC->MODE1.STATUS.bit.SYNCBUSY);
    RTC->MODE1.READREQ.reg |= RTC_READREQ_RCONT | RTC_READREQ_ADDR(0x10);
    RTC->MODE1.INTENSET.reg = RTC_MODE1_INTENSET_OVF;
    RTC->MODE1.CTRL.bit.ENABLE = 1;
    while (RTC->MODE1.STATUS.bit.SYNCBUSY);

    NVIC_EnableIRQ(RTC_IRQn);

}
static void poweron(pwm_t dev)
{
    PM->APBCMASK.reg |= (PM_APBCMASK_TCC0 << _num(dev));
    GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_CLKEN |
                         GCLK_CLKCTRL_GEN_GCLK0 |
                         GCLK_CLKCTRL_ID(_clk_id(dev)));
    while (GCLK->STATUS.bit.SYNCBUSY) {}
}
Example #7
0
void
enable_pclock(uint32_t clock_id, uint32_t pmask)
{
    GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_ID(clock_id) | GCLK_CLKCTRL_GEN_GCLK0
                         | GCLK_CLKCTRL_CLKEN);
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
        ;
    PM->APBCMASK.reg |= pmask;
}
void pwm_poweroff(pwm_t dev)
{
    _tcc(dev)->CTRLA.reg &= ~(TCC_CTRLA_ENABLE);

    PM->APBCMASK.reg &= ~(PM_APBCMASK_TCC0 << _num(dev));
    GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_GEN_GCLK7 |
                         GCLK_CLKCTRL_ID(_clk_id(dev)));
    while (GCLK->STATUS.bit.SYNCBUSY) {}
}
Example #9
0
File: rtt.c Project: adjih/RIOT
/**
 * @brief Initialize RTT module
 *
 * The RTT is running at 32768 Hz by default, i.e. @ XOSC32K frequency without
 * divider. There are 2 cascaded dividers in the clock path:
 *
 *  - GCLK_GENDIV_DIV(n): between 1 and 31
 *  - RTC_MODE0_CTRL_PRESCALER_DIVn: between 1 and 1024, see defines in `component_rtc.h`
 *
 * However the division scheme of GCLK_GENDIV_DIV can be changed by setting
 * GCLK_GENCTRL_DIVSEL:
 *
 *  - GCLK_GENCTRL_DIVSEL = 0: Clock divided by GENDIV.DIV (default)
 *  - GCLK_GENCTRL_DIVSEL = 1: Clock divided by 2^( GENDIV.DIV + 1 )
 */
void rtt_init(void)
{
    RtcMode0 *rtcMode0 = &(RTT_DEV);

    /* Turn on power manager for RTC */
    PM->APBAMASK.reg |= PM_APBAMASK_RTC;

    /* RTC uses External 32,768KHz Oscillator because OSC32K isn't accurate
     * enough (p1075/1138). Also keep running in standby. */
    SYSCTRL->XOSC32K.reg =  SYSCTRL_XOSC32K_ONDEMAND |
                            SYSCTRL_XOSC32K_EN32K |
                            SYSCTRL_XOSC32K_XTALEN |
                            SYSCTRL_XOSC32K_STARTUP(6) |
#if RTT_RUNSTDBY
                            SYSCTRL_XOSC32K_RUNSTDBY |
#endif
                            SYSCTRL_XOSC32K_ENABLE;

    /* Setup clock GCLK2 with divider 1 */
    GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(1);
    while (GCLK->STATUS.bit.SYNCBUSY) {}

    /* Enable GCLK2 with XOSC32K as source. Use divider without modification
     * and keep running in standby. */
    GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) |
                        GCLK_GENCTRL_GENEN |
#if RTT_RUNSTDBY
                        GCLK_GENCTRL_RUNSTDBY |
#endif
                        GCLK_GENCTRL_SRC_XOSC32K;
    while (GCLK->STATUS.bit.SYNCBUSY) {}

    /* Connect GCLK2 to RTC */
    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN_GCLK2 |
                        GCLK_CLKCTRL_CLKEN |
                        GCLK_CLKCTRL_ID(RTC_GCLK_ID);
    while (GCLK->STATUS.bit.SYNCBUSY) {}

    /* Disable RTC */
    rtt_poweroff();

    /* Reset RTC */
    rtcMode0->CTRL.bit.SWRST = 1;
    while (rtcMode0->STATUS.bit.SYNCBUSY || rtcMode0->CTRL.bit.SWRST) {}

    /* Configure as 32bit counter with no prescaler and no clear on match compare */
    rtcMode0->CTRL.reg = RTC_MODE0_CTRL_MODE_COUNT32 |
                         RTT_PRESCALER;
    while (rtcMode0->STATUS.bit.SYNCBUSY) {}

    /* Setup interrupt */
    NVIC_EnableIRQ(RTT_IRQ);

    /* Enable RTC */
    rtt_poweron();
}
Example #10
0
void SERCOM::initClockNVIC( void )
{
    uint8_t clockId = 0;
    IRQn_Type IdNvic=PendSV_IRQn ; // Dummy init to intercept potential error later

    if(sercom == SERCOM0)
    {
        clockId = GCM_SERCOM0_CORE;
        IdNvic = SERCOM0_IRQn;
    }
    else if(sercom == SERCOM1)
    {
        clockId = GCM_SERCOM1_CORE;
        IdNvic = SERCOM1_IRQn;
    }
    else if(sercom == SERCOM2)
    {
        clockId = GCM_SERCOM2_CORE;
        IdNvic = SERCOM2_IRQn;
    }
    else if(sercom == SERCOM3)
    {
        clockId = GCM_SERCOM3_CORE;
        IdNvic = SERCOM3_IRQn;
    }
    else if(sercom == SERCOM4)
    {
        clockId = GCM_SERCOM4_CORE;
        IdNvic = SERCOM4_IRQn;
    }
    else if(sercom == SERCOM5)
    {
        clockId = GCM_SERCOM5_CORE;
        IdNvic = SERCOM5_IRQn;
    }

    if ( IdNvic == PendSV_IRQn )
    {
        // We got a problem here
        return ;
    }

    // Setting NVIC
    NVIC_EnableIRQ(IdNvic);
    NVIC_SetPriority (IdNvic, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority */

    //Setting clock
    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
                        GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
                        GCLK_CLKCTRL_CLKEN ;

    while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
    {
        /* Wait for synchronization */
    }
}
void USBDeviceClass::init()
{
#ifdef PIN_LED_TXL
	txLEDPulse = 0;
	pinMode(PIN_LED_TXL, OUTPUT);
	digitalWrite(PIN_LED_TXL, HIGH);
#endif

#ifdef PIN_LED_RXL
	rxLEDPulse = 0;
	pinMode(PIN_LED_RXL, OUTPUT);
	digitalWrite(PIN_LED_RXL, HIGH);
#endif

	// Enable USB clock
	PM->APBBMASK.reg |= PM_APBBMASK_USB;

	// Set up the USB DP/DN pins
	PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
	PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));

	// Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6)     | // Generic Clock Multiplexer 6
	                    GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
	                    GCLK_CLKCTRL_CLKEN;
	while (GCLK->STATUS.bit.SYNCBUSY)
		;

	USB_SetHandler(&UDD_Handler);

	// Reset USB Device
	usbd.reset();

	usbd.calibrate();
	usbd.setUSBDeviceMode();
	usbd.runInStandby();
	usbd.setFullSpeed();

	// Configure interrupts
	NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
	NVIC_EnableIRQ((IRQn_Type) USB_IRQn);

	usbd.enable();

	initialized = true;
}
Example #12
0
/** Configures and starts the DFLL in closed loop mode with the given reference
 *  generator.
 *
 *  \param[in]  source_generator  Reference generator to use for the DFLL
 */
static void init_dfll(
		const enum system_clock_source source_generator)
{
	struct system_gclk_gen_config cpu_clock_conf;
	system_gclk_gen_get_config_defaults(&cpu_clock_conf);
	cpu_clock_conf.output_enable = ENABLE_CPU_CLOCK_OUT;

	/* Switch to OSC8M/OSC16M while the DFLL is being reconfigured */
#if SAML21
	cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_OSC16M;
#else
	cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_OSC8M;
#endif
	system_gclk_gen_set_config(GCLK_GENERATOR_0, &cpu_clock_conf);

	/* Turn off DFLL before adjusting its configuration */
	system_clock_source_disable(SYSTEM_CLOCK_SOURCE_DFLL);

	/* Configure DFLL reference clock, use raw register write to
	 * force-configure the channel even if the currently selected generator
	 * clock has failed */
#if SAML21
        GCLK->PCHCTRL[SYSCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_GEN(source_generator);      
#else
	GCLK->CLKCTRL.reg =
			GCLK_CLKCTRL_ID(SYSCTRL_GCLK_ID_DFLL48) |
			GCLK_CLKCTRL_GEN(source_generator);
#endif
	system_gclk_chan_enable(SYSCTRL_GCLK_ID_DFLL48);

	/* Configure DFLL */
	struct system_clock_source_dfll_config config_dfll;
	system_clock_source_dfll_get_config_defaults(&config_dfll);
	config_dfll.on_demand = false;
	config_dfll.loop_mode = SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED;
	config_dfll.multiply_factor =
			(48000000UL / system_gclk_chan_get_hz(SYSCTRL_GCLK_ID_DFLL48));
	system_clock_source_dfll_set_config(&config_dfll);

	/* Restart DFLL */
	system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DFLL);
	while (system_clock_source_is_ready(SYSTEM_CLOCK_SOURCE_DFLL) == false) {
		/* Wait for DFLL to be stable before switch back */
	}

	/* Switch back to the DFLL as the CPU clock source */
	cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_DFLL;
	system_gclk_gen_set_config(GCLK_GENERATOR_0, &cpu_clock_conf);
};
Example #13
0
/*************************************************************************//**
*****************************************************************************/
void HAL_UartInit(uint32_t baudrate)
{
  uint64_t brr = (uint64_t)65536 * (F_CPU - 16 * baudrate) / F_CPU;

  HAL_GPIO_UART_TXD_out();
  HAL_GPIO_UART_TXD_pmuxen();
  HAL_GPIO_UART_RXD_in();
  HAL_GPIO_UART_RXD_pmuxen();

  PORTA_PMUX12 = PORTA_PMUX12_PMUXE(2/*C*/) | PORTA_PMUX12_PMUXO(2/*C*/);

  PM_APBCMASK |= PM_APBCMASK_SERCOM3;

  GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_ID(0x10/*SERCOM3_CORE*/) | GCLK_CLKCTRL_GEN(0);

  SC3_USART_CTRLA = SC3_USART_CTRLA_MODE(1/*USART*/) | SC3_USART_CTRLA_DORD |
      SC3_USART_CTRLA_RXPO(3/*PAD3*/) | SC3_USART_CTRLA_TXPO/*PAD2*/;
  halUartSync();

  SC3_USART_CTRLB = SC3_USART_CTRLB_TXEN | SC3_USART_CTRLB_RXEN | SC3_USART_CTRLB_CHSIZE(0/*8 bits*/);
  halUartSync();

  SC3_USART_BAUD = (uint16_t)brr;
  halUartSync();

  SC3_USART_CTRLA |= SC3_USART_CTRLA_ENABLE;
  halUartSync();

  SC3_USART_INTENSET = SC3_USART_INTENSET_RXC;
  NVIC_ISER = NVIC_ISER_SERCOM3;

  txFifo.data = txData;
  txFifo.size = HAL_UART_TX_FIFO_SIZE;
  txFifo.bytes = 0;
  txFifo.head = 0;
  txFifo.tail = 0;

  rxFifo.data = rxData;
  rxFifo.size = HAL_UART_RX_FIFO_SIZE;
  rxFifo.bytes = 0;
  rxFifo.head = 0;
  rxFifo.tail = 0;

  udrEmpty = true;
  newData = false;
}
Example #14
0
void
SystemInit(void)
{
    // Setup flash to work with 48Mhz clock
    NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_RWS_HALF;

    // Enable external 32Khz crystal
    uint32_t val = (SYSCTRL_XOSC32K_STARTUP(6)
                    | SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K);
    SYSCTRL->XOSC32K.reg = val;
    SYSCTRL->XOSC32K.reg = val | SYSCTRL_XOSC32K_ENABLE;
    while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY))
        ;

    // Reset GCLK
    GCLK->CTRL.reg = GCLK_CTRL_SWRST;
    while (GCLK->CTRL.reg & GCLK_CTRL_SWRST)
        ;

    // Route 32Khz clock to DFLL48M
    GCLK->GENDIV.reg = GCLK_GENDIV_ID(CLK_32K);
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_ID(CLK_32K)
                         | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_GENEN);
    GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_ID(MCLK_DFLL48M)
                         | GCLK_CLKCTRL_GEN(CLK_32K) | GCLK_CLKCTRL_CLKEN);

    // Configure DFLL48M clock
    SYSCTRL->DFLLCTRL.reg = 0;
    uint32_t mul = DIV_ROUND_CLOSEST(CONFIG_CLOCK_FREQ, CLK_32K_FREQ);
    SYSCTRL->DFLLMUL.reg = (SYSCTRL_DFLLMUL_CSTEP(31)
                            | SYSCTRL_DFLLMUL_FSTEP(511)
                            | SYSCTRL_DFLLMUL_MUL(mul));
    SYSCTRL->DFLLCTRL.reg = (SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_WAITLOCK
                             | SYSCTRL_DFLLCTRL_QLDIS
                             | SYSCTRL_DFLLCTRL_ENABLE);
    uint32_t ready = (SYSCTRL_PCLKSR_DFLLRDY | SYSCTRL_PCLKSR_DFLLLCKC
                      | SYSCTRL_PCLKSR_DFLLLCKF);
    while ((SYSCTRL->PCLKSR.reg & ready) != ready)
        ;

    // Switch main clock to DFLL48M clock
    GCLK->GENDIV.reg = GCLK_GENDIV_ID(CLK_MAIN);
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_ID(CLK_MAIN)
                         | GCLK_GENCTRL_SRC_DFLL48M
                         | GCLK_GENCTRL_IDC | GCLK_GENCTRL_GENEN);
}
Example #15
0
/*************************************************************************//**
*****************************************************************************/
void halPhyInit(void)
{
  // Configure IO pins
  HAL_GPIO_PHY_SLP_TR_out();
  HAL_GPIO_PHY_SLP_TR_clr();
  HAL_GPIO_PHY_RST_out();
  HAL_GPIO_PHY_IRQ_in();
  HAL_GPIO_PHY_IRQ_pmuxen();
  HAL_GPIO_PHY_CS_out();
  HAL_GPIO_PHY_MISO_in();
  HAL_GPIO_PHY_MISO_pmuxen();
  HAL_GPIO_PHY_MOSI_out();
  HAL_GPIO_PHY_MOSI_pmuxen();
  HAL_GPIO_PHY_SCK_out();
  HAL_GPIO_PHY_SCK_pmuxen();

  // Configure SPI
  PORT->Group[HAL_GPIO_PORTA].PMUX[9].bit.PMUXE = 2/*C*/; // MOSI
  PORT->Group[HAL_GPIO_PORTA].PMUX[9].bit.PMUXO = 2/*C*/; // SCK
  PORT->Group[HAL_GPIO_PORTA].PMUX[8].bit.PMUXE = 2/*C*/; // MISO

  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM1;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM1_GCLK_ID_CORE) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

  SERCOM1->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_RXEN;
  halPhySpiSync();

#if F_CPU <= 16000000
  SERCOM1->SPI.BAUD.reg = 0;
#elif F_CPU <= 32000000
  SERCOM1->SPI.BAUD.reg = 1;
#elif F_CPU <= 48000000
  SERCOM1->SPI.BAUD.reg = 2;
#else
  #error Unsupported frequency
#endif

  SERCOM1->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
      SERCOM_SPI_CTRLA_DIPO(0) | SERCOM_SPI_CTRLA_DOPO;
  halPhySpiSync();
}
Example #16
0
//-----------------------------------------------------------------------------
static void timer_init(void)
{
  PM->APBCMASK.reg |= PM_APBCMASK_TC1;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(TC1_GCLK_ID) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

  TC1->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ |
      TC_CTRLA_PRESCALER_DIV256 | TC_CTRLA_PRESCSYNC_RESYNC;

  TC1->COUNT16.COUNT.reg = 0;

  timer_set_period(PERIOD_SLOW);

  TC1->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;

  TC1->COUNT16.INTENSET.reg = TC_INTENSET_MC(1);
  NVIC_EnableIRQ(TC1_IRQn);
}
Example #17
0
void SaLBuzzerInit() {

    pinOut(BUZZER);
    pinCfg(BUZZER);
//
    PM->APBCMASK.reg |= PM_APBCMASK_TC5;
//
    GCLK->GENDIV.reg =  GCLK_GENDIV_ID(5) |
                        GCLK_GENDIV_DIV(1);
    GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(5) |
                        GCLK_GENCTRL_SRC_OSC8M |
                        GCLK_GENCTRL_GENEN;

    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN(0) |
                        GCLK_CLKCTRL_CLKEN |
                        GCLK_CLKCTRL_ID(TC5_GCLK_ID);


    TC5->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16|
                             TC_CTRLA_RUNSTDBY |
                             //	 TC_CTRLA_PRESCSYNC_GCLK |
                             TC_CTRLA_PRESCALER_DIV4;

    // TC5->COUNT16.EVCTRL.bit.EVACT = 0x1;

    TC5->COUNT16.CC[0].bit.CC = 700;

    //TC5->COUNT16.PER.reg = 0x02;

    TC5->COUNT16.INTENSET.reg = TC_INTENSET_MC0;

    TC5->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;

    TC5->COUNT16.EVCTRL.bit.EVACT = 0x1;


    NVIC_EnableIRQ(TC5_IRQn);
    NVIC_SetPriority(TC5_IRQn,0xFFF);

    TC5->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_STOP;
}
// ****************************************************************************
void HAL_spi_init(void)
{
    // Use GLKGEN0 (48 MHz) as clock source for SPI
    GCLK->CLKCTRL.reg =
        GCLK_CLKCTRL_ID(SPI_SERCOM_GCLK_ID) |
        GCLK_CLKCTRL_CLKEN |
        GCLK_CLKCTRL_GEN(0);

    // Reset the peripheral
    SPI_SERCOM->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_SWRST;
    while (SPI_SERCOM->SPI.CTRLA.reg & SERCOM_SPI_CTRLA_SWRST);

    // 12 MHz SPI clock @ 48 MHz
    SPI_SERCOM->SPI.BAUD.reg = 1;

    // Enable the SPI master, mode 0
    SPI_SERCOM->SPI.CTRLA.reg =
        SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
        SERCOM_SPI_CTRLA_DOPO(0) |
        SERCOM_SPI_CTRLA_ENABLE ;
}
Example #19
0
/* Configure I/O interrupt sources */
static void __initialize()
{
  memset(callbacksInt, 0, sizeof(callbacksInt));

  NVIC_DisableIRQ(EIC_IRQn);
  NVIC_ClearPendingIRQ(EIC_IRQn);
  NVIC_SetPriority(EIC_IRQn, 0);
  NVIC_EnableIRQ(EIC_IRQn);

  // Enable GCLK for IEC (External Interrupt Controller)
  GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC));

/* Shall we do that?
  // Do a software reset on EIC
  EIC->CTRL.SWRST.bit = 1 ;
  while ((EIC->CTRL.SWRST.bit == 1) && (EIC->STATUS.SYNCBUSY.bit == 1)) { }
*/

  // Enable EIC
  EIC->CTRL.bit.ENABLE = 1;
  while (EIC->STATUS.bit.SYNCBUSY == 1) { }
}
Example #20
0
File: udc.c Project: ataradov/dgw
//-----------------------------------------------------------------------------
void udc_init(void)
{
  HAL_GPIO_USB_DM_pmuxen(PORT_PMUX_PMUXE_G_Val);
  HAL_GPIO_USB_DP_pmuxen(PORT_PMUX_PMUXE_G_Val);

  PM->APBBMASK.reg |= PM_APBBMASK_USB;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_ID(USB_GCLK_ID) |
      GCLK_CLKCTRL_GEN(0);

  USB->DEVICE.CTRLA.bit.SWRST = 1;
  while (USB->DEVICE.SYNCBUSY.bit.SWRST);

  USB->DEVICE.PADCAL.bit.TRANSN = NVM_READ_CAL(USB_TRANSN);
  USB->DEVICE.PADCAL.bit.TRANSP = NVM_READ_CAL(USB_TRANSP);
  USB->DEVICE.PADCAL.bit.TRIM   = NVM_READ_CAL(USB_TRIM);

  memset((uint8_t *)udc_mem, 0, sizeof(udc_mem));
  USB->DEVICE.DESCADD.reg = (uint32_t)udc_mem;

  USB->DEVICE.CTRLA.bit.MODE = USB_CTRLA_MODE_DEVICE_Val;
  USB->DEVICE.CTRLA.bit.RUNSTDBY = 1;
  USB->DEVICE.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val;
  USB->DEVICE.CTRLB.bit.DETACH = 0;

  USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_EORST;
  USB->DEVICE.DeviceEndpoint[0].EPINTENSET.bit.RXSTP = 1;

  USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE;

  for (int i = 0; i < USB_EPT_NUM; i++)
  {
    udc_reset_endpoint(i, USB_IN_ENDPOINT);
    udc_reset_endpoint(i, USB_OUT_ENDPOINT);
  }

  NVIC_EnableIRQ(USB_IRQn);
}
Example #21
0
void main_clock_init (void)
{
	/* enable the xosc32k and set the start up time */
	SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP(6) | SYSCTRL_XOSC32K_EN32K |
												 SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_ENABLE;
	
	while (!SYSCTRL->PCLKSR.bit.XOSC32KRDY){}
	
	/* enable the generic clock GEN1 and configure the XOSC32K as clock source for it */
	GCLK->GENCTRL.reg = GCLK_GENCTRL_ID_GCLK1 | GCLK_GENCTRL_SRC_XOSC32K | 
											GCLK_GENCTRL_GENEN | GCLK_GENCTRL_IDC;
	
	while (GCLK->STATUS.bit.SYNCBUSY){}
	
	/* Enable the DFLL and set the operation mode as closed loop */
  SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE | SYSCTRL_DFLLCTRL_MODE;
  
  while(!SYSCTRL->PCLKSR.bit.DFLLRDY){}
		
  /* Load the Multiply factor, Coarse Step and fine Step for DFLL */
  SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(0x1F/4) | SYSCTRL_DFLLMUL_FSTEP(0xFF/4) |  
												 SYSCTRL_DFLLMUL_MUL(1465);
		
  /* Enable the Generic Clock GEN 1 as DFLL48 as Reference */ 
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID(0);
  /* wait for fine lock */
  while(!SYSCTRL->PCLKSR.bit.DFLLLCKF){}
		
  /* Set the NVM Read Wait States to 1, Since the operating frequency 48 MHz */
  NVMCTRL->CTRLB.bit.RWS = 1;
		
  /*  Enable the Generic Clock 0 and Configure the DFLL as Clock Source for it*/
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID_GCLK0 | GCLK_GENCTRL_SRC_DFLL48M |  GCLK_GENCTRL_GENEN | 
											GCLK_GENCTRL_IDC;
  
  while(GCLK->STATUS.bit.SYNCBUSY){}		
}
// ****************************************************************************
void HAL_uart_init(uint32_t baudrate)
{
    #define UART_CLK 48000000

    uint64_t brr = (uint64_t)65536 * (UART_CLK - 16 * baudrate) / UART_CLK;

    // Use GLKGEN0 (48 MHz) as clock source for the UART
    GCLK->CLKCTRL.reg =
        GCLK_CLKCTRL_ID(UART_SERCOM_GCLK_ID) |
        GCLK_CLKCTRL_CLKEN |
        GCLK_CLKCTRL_GEN(0);

    // Run UART from GCLK; Setup Rx and Tx pads
    UART_SERCOM->USART.CTRLA.reg =
        SERCOM_USART_CTRLA_DORD |
        SERCOM_USART_CTRLA_MODE_USART_INT_CLK |
        SERCOM_USART_CTRLA_RXPO(HAL_GPIO_RX.rxpo) |
        SERCOM_USART_CTRLA_TXPO(tx_pad);

    // Enable transmit and receive; 8 bit characters
    UART_SERCOM->USART.CTRLB.reg =
        SERCOM_USART_CTRLB_RXEN |
        SERCOM_USART_CTRLB_TXEN |
        SERCOM_USART_CTRLB_CHSIZE(0);           // 8 bits
    while (UART_SERCOM->USART.SYNCBUSY.reg);

    UART_SERCOM->USART.BAUD.reg = (uint16_t)brr;
    while (UART_SERCOM->USART.SYNCBUSY.reg);

    UART_SERCOM->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;
    while (UART_SERCOM->USART.SYNCBUSY.reg);

    // Enable the receive interrupt
    UART_SERCOM->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC;
    NVIC_EnableIRQ(UART_SERCOM_IRQN);
}
Example #23
0
/*************************************************************************//**
*****************************************************************************/
void HAL_TimerInit(void)
{
  halTimerIrqCount = 0;

  PM_APBCMASK |= PM_APBCMASK_TC4;

  GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_ID(0x15/*TC4,TC5*/) | GCLK_CLKCTRL_GEN(0);

  TC4_16_CTRLA = TC4_16_CTRLA_MODE(0/*16 bit*/) | TC4_16_CTRLA_WAVEGEN(1/*MFRQ*/) |
      TC4_16_CTRLA_PRESCALER(3/*DIV8*/) | TC4_16_CTRLA_PRESCSYNC(0x1/*PRESC*/);
  halTimerSync();

  TC4_16_COUNT = 0;
  halTimerSync();

  TC4_16_CC0 = TIMER_TOP;
  halTimerSync();

  TC4_16_CTRLA |= TC4_16_CTRLA_ENABLE;
  halTimerSync();

  TC4_16_INTENSET = TC4_16_INTENSET_MC0;
  NVIC_ISER = NVIC_ISER_TC4;
}
void UDD_Init(void)
{
	uint32_t pad_transn;
    uint32_t pad_transp;
    uint32_t pad_trim;
	uint32_t i;

	/* Enable USB clock */
	PM->APBBMASK.reg |= PM_APBBMASK_USB;

	/* Set up the USB DP/DN pins */
	PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
	PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));

	/* ----------------------------------------------------------------------------------------------
	 * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
	 */
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( 6 ) | // Generic Clock Multiplexer 6
					GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
					GCLK_CLKCTRL_CLKEN ;

	while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
	{
	/* Wait for synchronization */
	}

	/* Reset */
	USB->DEVICE.CTRLA.bit.SWRST = 1;
	while (USB->DEVICE.SYNCBUSY.bit.SWRST) {
		/* Sync wait */
	}

	udd_enable();

	/* Load Pad Calibration */
	pad_transn =( *((uint32_t *)(NVMCTRL_OTP4)  // Non-Volatile Memory Controller
	+ (NVM_USB_PAD_TRANSN_POS / 32))
	>> (NVM_USB_PAD_TRANSN_POS % 32))
	& ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);

	if (pad_transn == 0x1F) {  // maximum value (31)
		pad_transn = 5;
	}

	USB->DEVICE.PADCAL.bit.TRANSN = pad_transn;

	pad_transp =( *((uint32_t *)(NVMCTRL_OTP4)
	+ (NVM_USB_PAD_TRANSP_POS / 32))
	>> (NVM_USB_PAD_TRANSP_POS % 32))
	& ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);

	if (pad_transp == 0x1F) {  // maximum value (31)
		pad_transp = 29;
	}

	USB->DEVICE.PADCAL.bit.TRANSP = pad_transp;

	pad_trim =( *((uint32_t *)(NVMCTRL_OTP4)
	+ (NVM_USB_PAD_TRIM_POS / 32))
	>> (NVM_USB_PAD_TRIM_POS % 32))
	& ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);

	if (pad_trim == 0x7) {  // maximum value (7)
		pad_trim = 3;
	}

	USB->DEVICE.PADCAL.bit.TRIM = pad_trim;

	/* Set the configuration */
	udd_force_device_mode();
	udd_device_run_in_standby();
    // Set address of USB SRAM
	USB->DEVICE.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]);
	// For USB_SPEED_FULL
	udd_force_full_speed();
 	for (i = 0; i < sizeof(usb_endpoint_table); i++) {
 		(*(uint32_t *)(&usb_endpoint_table[0]+i)) = 0;
 	}

	// Configure interrupts
	NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
	NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
}
void SystemInit( void )
{
  /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
  NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val ;

  /* Turn on the digital interface clock */
  PM->APBAMASK.reg |= PM_APBAMASK_GCLK ;

  /* ----------------------------------------------------------------------------------------------
   * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
   */
  SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */
                         SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ;
  SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */

  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 )
  {
    /* Wait for oscillator stabilization */
  }

  /* Software reset the module to ensure it is re-initialized correctly */
  /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
   * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
   */
  GCLK->CTRL.reg = GCLK_CTRL_SWRST ;

  while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) )
  {
    /* Wait for reset to complete */
  }

  /* ----------------------------------------------------------------------------------------------
   * 2) Put XOSC32K as source of Generic Clock Generator 1
   */
  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1

  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
  {
    /* Wait for synchronization */
  }

  /* Write Generic Clock Generator 1 configuration */
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1
                      GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
                      GCLK_GENCTRL_GENEN ;

  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
  {
    /* Wait for synchronization */
  }

  /* ----------------------------------------------------------------------------------------------
   * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
   */
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0
                      GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source
                      GCLK_CLKCTRL_CLKEN ;

  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
  {
    /* Wait for synchronization */
  }

  /* ----------------------------------------------------------------------------------------------
   * 4) Enable DFLL48M clock
   */

  /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */

  /* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */
  SYSCTRL->DFLLCTRL.bit.ONDEMAND = 0 ;

  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
  {
    /* Wait for synchronization */
  }

  SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value
                         SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value
                         SYSCTRL_DFLLMUL_MUL( (__CLOCK_48MHz/__CLOCK_32KHz) ) ; // External 32KHz is the reference

  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
  {
    /* Wait for synchronization */
  }

  /* Write full configuration to DFLL control register */
  SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
                           SYSCTRL_DFLLCTRL_WAITLOCK |
                           SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */

  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
  {
    /* Wait for synchronization */
  }

  /* Enable the DFLL */
  SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;

  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 ||
          (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 )
  {
    /* Wait for locks flags */
  }

  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
  {
    /* Wait for synchronization */
  }

  /* ----------------------------------------------------------------------------------------------
   * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
   */
  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ) ; // Generic Clock Generator 0

  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
  {
    /* Wait for synchronization */
  }

  /* Write Generic Clock Generator 0 configuration */
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0
                      GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz
//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
                      GCLK_GENCTRL_IDC | // Set 50/50 duty cycle
                      GCLK_GENCTRL_GENEN ;

  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
  {
    /* Wait for synchronization */
  }

  /* ----------------------------------------------------------------------------------------------
   * 6) Modify PRESCaler value of OSC8M to have 8MHz
   */
  SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_0_Val ;
  SYSCTRL->OSC8M.bit.ONDEMAND = 0 ;

  /* ----------------------------------------------------------------------------------------------
   * 7) Put OSC8M as source for Generic Clock Generator 3
   */
  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) ; // Generic Clock Generator 3

  /* Write Generic Clock Generator 3 configuration */
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3
                      GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset)
//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
                      GCLK_GENCTRL_GENEN ;

  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
  {
    /* Wait for synchronization */
  }

  /* ----------------------------------------------------------------------------------------------
   * 8) Put OSC8M as source for Generic Clock Generator 2, with freq/8
   */
  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC1M ) | 8 << 8; // Generic Clock Generator 4

  /* Write Generic Clock Generator 3 configuration */
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC1M ) | // Generic Clock Generator 4
                      GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset)
//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
                      GCLK_GENCTRL_GENEN ;

  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
  {
    /* Wait for synchronization */
  }

  /*
   * Now that all system clocks are configured, we can set CPU and APBx BUS clocks.
   * There values are normally the one present after Reset.
   */
  PM->CPUSEL.reg  = PM_CPUSEL_CPUDIV_DIV1 ;
  PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val ;
  PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val ;
  PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val ;

  SystemCoreClock=__CLOCK_48MHz ;

	return;
}
/*
 * Arduino Zero board initialization
 *
 * Good to know:
 *   - At reset, ResetHandler did the system clock configuration. Core is running at 48MHz.
 *   - Watchdog is disabled by default, unless someone plays with NVM User page
 *   - During reset, all PORT lines are configured as inputs with input buffers, output buffers and pull disabled.
 */
void init( void )
{
  uint32_t ul ;

  // Set Systick to 1ms interval, common to all Cortex-M variants
  if ( SysTick_Config( SystemCoreClock / 1000 ) )
  {
    // Capture error
    while ( 1 ) ;
  }

  // Clock PORT for Digital I/O
//  PM->APBBMASK.reg |= PM_APBBMASK_PORT ;
//
//  // Clock EIC for I/O interrupts
//  PM->APBAMASK.reg |= PM_APBAMASK_EIC ;

  // Clock SERCOM for Serial
  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0 | PM_APBCMASK_SERCOM1 | PM_APBCMASK_SERCOM2 | PM_APBCMASK_SERCOM3 | PM_APBCMASK_SERCOM4 | PM_APBCMASK_SERCOM5 ;

  // Clock TC/TCC for Pulse and Analog
  PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 ;

  // Clock ADC/DAC for Analog
  PM->APBCMASK.reg |= PM_APBCMASK_ADC ;//| PM_APBCMASK_DAC ;

  // Setup all pins (digital and analog) in INPUT mode (default is nothing)
  for ( ul = 0 ; ul < NUM_DIGITAL_PINS ; ul++ )
  {
    pinMode( ul, INPUT ) ;
  }

  // Initialize Analog Controller
  // Setting clock
  while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC
                      GCLK_CLKCTRL_GEN_GCLK0     | // Generic Clock Generator 0 is source
                      GCLK_CLKCTRL_CLKEN ;

  while( ADC->STATUS.bit.SYNCBUSY == 1 );          // Wait for synchronization of registers between the clock domains

  ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 |    // Divide Clock by 512.
                   ADC_CTRLB_RESSEL_10BIT;         // 10 bits resolution as default

  ADC->SAMPCTRL.reg = 0x3f;                        // Set max Sampling Time Length

  while( ADC->STATUS.bit.SYNCBUSY == 1 );          // Wait for synchronization of registers between the clock domains

  ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND;   // No Negative input (Internal Ground)

  // Averaging (see datasheet table in AVGCTRL register description)
  ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 |    // 1 sample only (no oversampling nor averaging)
                     ADC_AVGCTRL_ADJRES(0x0ul);   // Adjusting result by 0

  analogReference( AR_DEFAULT ) ; // Analog Reference is AREF pin (3.3v)

  // Initialize DAC
  // Setting clock
  // while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY );
  // GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_DAC ) | // Generic Clock ADC
  //                     GCLK_CLKCTRL_GEN_GCLK0     | // Generic Clock Generator 0 is source
  //                     GCLK_CLKCTRL_CLKEN ;

  // while ( DAC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
  // DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference
  //                  DAC_CTRLB_EOEN ;        // External Output Enable (Vout)
}
void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
{
  if (toneIsActive && (outputPin != lastOutputPin))
    noTone(lastOutputPin);

  //
  // Calculate best prescaler divider and comparator value for a 16 bit TC peripheral
  //

  uint32_t prescalerConfigBits;
  uint32_t ccValue;

  ccValue = toneMaxFrequency / frequency - 1;
  prescalerConfigBits = TC_CTRLA_PRESCALER_DIV1;

  if (ccValue > TONE_TC_TOP)
  {
    ccValue = toneMaxFrequency / frequency / 2 - 1;
    prescalerConfigBits = TC_CTRLA_PRESCALER_DIV2;

    if (ccValue > TONE_TC_TOP)
    {
      ccValue = toneMaxFrequency / frequency / 4 - 1;
      prescalerConfigBits = TC_CTRLA_PRESCALER_DIV4;

      if (ccValue > TONE_TC_TOP)
      {
        ccValue = toneMaxFrequency / frequency / 8 - 1;
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV8;

        if (ccValue > TONE_TC_TOP)
        {
          ccValue = toneMaxFrequency / frequency / 16 - 1;
          prescalerConfigBits = TC_CTRLA_PRESCALER_DIV16;

          if (ccValue > TONE_TC_TOP)
          {
            ccValue = toneMaxFrequency / frequency / 64 - 1;
            prescalerConfigBits = TC_CTRLA_PRESCALER_DIV64;

            if (ccValue > TONE_TC_TOP)
            {
              ccValue = toneMaxFrequency / frequency / 256 - 1;
              prescalerConfigBits = TC_CTRLA_PRESCALER_DIV256;

              if (ccValue > TONE_TC_TOP)
              {
                ccValue = toneMaxFrequency / frequency / 1024 - 1;
                prescalerConfigBits = TC_CTRLA_PRESCALER_DIV1024;
              }
            }
          }
        }
      }
    }
  }

  toggleCount = (duration > 0 ? frequency * duration * 2 / 1000UL : -1);

  // Enable GCLK for TC4 and TC5 (timer counter input clock)
  GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5));
  while (GCLK->STATUS.bit.SYNCBUSY);

  resetTC(TONE_TC);

  // Set Timer counter Mode to 16 bits
  TONE_TC->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16;

  // Set TONE_TC mode as match frequency
  TONE_TC->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;

  TONE_TC->COUNT16.CTRLA.reg |= prescalerConfigBits;

  TONE_TC->COUNT16.CC[TONE_TC_CHANNEL].reg = (uint16_t) ccValue;
  WAIT_TC16_REGS_SYNC(TONE_TC)

  // Configure interrupt request
  NVIC_DisableIRQ(TONE_TC_IRQn);
  NVIC_ClearPendingIRQ(TONE_TC_IRQn);
  NVIC_SetPriority(TONE_TC_IRQn, 0);
  NVIC_EnableIRQ(TONE_TC_IRQn);

  portToggleRegister = &(PORT->Group[g_APinDescription[outputPin].ulPort].OUTTGL.reg);
  portClearRegister = &(PORT->Group[g_APinDescription[outputPin].ulPort].OUTCLR.reg);
  portBitMask = (1ul << g_APinDescription[outputPin].ulPin);

  // Enable the TONE_TC interrupt request
  TONE_TC->COUNT16.INTENSET.bit.MC0 = 1;

  lastOutputPin = outputPin;
  digitalWrite(outputPin, LOW);
  pinMode(outputPin, OUTPUT);
  toneIsActive = true;

  // Enable TONE_TC
  TONE_TC->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;
  WAIT_TC16_REGS_SYNC(TONE_TC)
}
// Right now, PWM output only works on the pins with
// hardware support.  These are defined in the appropriate
// pins_*.c file.  For the rest of the pins, we default
// to digital output.
void analogFastWrite(uint32_t pin, uint32_t value)
{
  PinDescription pinDesc = g_APinDescription[pin];
  uint32_t attr = pinDesc.ulPinAttribute;

  if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
  {
    // DAC handling code

    if (pin != PIN_A0) { // Only 1 DAC on A0 (PA02)
      return;
    }

    value = mapResolution(value, _writeResolution, 10);

    syncDAC();
    DAC->DATA.reg = value & 0x3FF;  // DAC on 10 bits.
    syncDAC();
    DAC->CTRLA.bit.ENABLE = 0x01;     // Enable DAC
    syncDAC();
    return;
  }

  if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM)
  {
    value = mapResolution(value, _writeResolution, 8);  // change to 10 for 10 bit... must also change  TCx->COUNT8.PER.reg = 0x3FF
    uint32_t tcNum = GetTCNumber(pinDesc.ulPWMChannel);
    uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel);
    static bool tcEnabled[TCC_INST_NUM+TC_INST_NUM];

    if (!tcEnabled[tcNum]) {
      tcEnabled[tcNum] = true;

      if (attr & PIN_ATTR_TIMER) {
        #if !(ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10603)
        // Compatibility for cores based on SAMD core <=1.6.2
        if (pinDesc.ulPinType == PIO_TIMER_ALT) {
          pinPeripheral(pin, PIO_TIMER_ALT);
        } else
        #endif
        {
          pinPeripheral(pin, PIO_TIMER);
        }
      } else {
        // We suppose that attr has PIN_ATTR_TIMER_ALT bit set...
        pinPeripheral(pin, PIO_TIMER_ALT);
      }

      uint16_t GCLK_CLKCTRL_IDs[] = {
        GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC0
        GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC1
        GCLK_CLKCTRL_ID(GCM_TCC2_TC3),  // TCC2
        GCLK_CLKCTRL_ID(GCM_TCC2_TC3),  // TC3
        GCLK_CLKCTRL_ID(GCM_TC4_TC5),   // TC4
        GCLK_CLKCTRL_ID(GCM_TC4_TC5),   // TC5
        GCLK_CLKCTRL_ID(GCM_TC6_TC7),   // TC6
        GCLK_CLKCTRL_ID(GCM_TC6_TC7),   // TC7
      };
      GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_IDs[tcNum]);
      while (GCLK->STATUS.bit.SYNCBUSY == 1);

      // Set PORT
      if (tcNum >= TCC_INST_NUM) {
        // -- Configure TC
        Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
        // Disable TCx
        TCx->COUNT8.CTRLA.bit.ENABLE = 0;
        syncTC_8(TCx);
        // Set Timer counter Mode to 8 bits, normal PWM
        TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8 | TC_CTRLA_WAVEGEN_NPWM;
        syncTC_8(TCx);
        // Set the initial value
        TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
        syncTC_8(TCx);
        // Set PER to maximum counter value (resolution : 0xFF)
        TCx->COUNT8.PER.reg = 0xFF;
        syncTC_8(TCx);
        // Enable TCx
        TCx->COUNT8.CTRLA.bit.ENABLE = 1;
        syncTC_8(TCx);
      } else {
        // -- Configure TCC
        Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
        // Disable TCCx
        TCCx->CTRLA.bit.ENABLE = 0;
        syncTCC(TCCx);

        // Set TCx as normal PWM
        TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
        syncTCC(TCCx);
        // Set the initial value
        TCCx->CC[tcChannel].reg = (uint32_t) value;
        syncTCC(TCCx);
        // Set PER to maximum counter value (resolution : 0xFF)
        TCCx->PER.reg = 0xFF; //change to 0x43FF for 10 bit... must also change mapping above
        syncTCC(TCCx);
        // Enable TCCx
        TCCx->CTRLA.bit.ENABLE = 1;
        syncTCC(TCCx);
      }
    } else {
      if (tcNum >= TCC_INST_NUM) {
        Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
        TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
        syncTC_8(TCx);
    } else {
        Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
        TCCx->CTRLBSET.bit.LUPD = 1;
        syncTCC(TCCx);
        TCCx->CCB[tcChannel].reg = (uint32_t) value;
        syncTCC(TCCx);
        TCCx->CTRLBCLR.bit.LUPD = 1;
        syncTCC(TCCx);
      }
    }
    return;
  }

  // -- Defaults to digital write
  pinMode(pin, OUTPUT);
  value = mapResolution(value, _writeResolution, 8);
  if (value < 128) {
    digitalWrite(pin, LOW);
  } else {
    digitalWrite(pin, HIGH);
  }
}
Example #29
0
File: cpu.c Project: ant9000/RIOT
/**
 * @brief   Configure clock sources and the cpu frequency
 */
static void clk_init(void)
{
    /* enable clocks for the power, sysctrl and gclk modules */
    PM->APBAMASK.reg = (PM_APBAMASK_PM | PM_APBAMASK_SYSCTRL |
                        PM_APBAMASK_GCLK);

    /* adjust NVM wait states, see table 42.30 (p. 1070) in the datasheet */
#if (CLOCK_CORECLOCK > 24000000)
    PM->APBAMASK.reg |= PM_AHBMASK_NVMCTRL;
    NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(1);
    PM->APBAMASK.reg &= ~PM_AHBMASK_NVMCTRL;
#endif

    /* configure internal 8MHz oscillator to run without prescaler */
    SYSCTRL->OSC8M.bit.PRESC = 0;
    SYSCTRL->OSC8M.bit.ONDEMAND = 1;
    SYSCTRL->OSC8M.bit.RUNSTDBY = 0;
    SYSCTRL->OSC8M.bit.ENABLE = 1;
    while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC8MRDY)) {}

#if CLOCK_USE_PLL
    /* reset the GCLK module so it is in a known state */
    GCLK->CTRL.reg = GCLK_CTRL_SWRST;
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}

    /* setup generic clock 1 to feed DPLL with 1MHz */
    GCLK->GENDIV.reg = (GCLK_GENDIV_DIV(8) |
                        GCLK_GENDIV_ID(1));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_SRC_OSC8M |
                         GCLK_GENCTRL_ID(1));
    GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_GEN(1) |
                         GCLK_CLKCTRL_ID(1) |
                         GCLK_CLKCTRL_CLKEN);
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}

    /* enable PLL */
    SYSCTRL->DPLLRATIO.reg = (SYSCTRL_DPLLRATIO_LDR(CLOCK_PLL_MUL));
    SYSCTRL->DPLLCTRLB.reg = (SYSCTRL_DPLLCTRLB_REFCLK_GCLK);
    SYSCTRL->DPLLCTRLA.reg = (SYSCTRL_DPLLCTRLA_ENABLE);
    while(!(SYSCTRL->DPLLSTATUS.reg &
           (SYSCTRL_DPLLSTATUS_CLKRDY | SYSCTRL_DPLLSTATUS_LOCK))) {}

    /* select the PLL as source for clock generator 0 (CPU core clock) */
    GCLK->GENDIV.reg =  (GCLK_GENDIV_DIV(CLOCK_PLL_DIV) |
                        GCLK_GENDIV_ID(0));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_SRC_FDPLL |
                         GCLK_GENCTRL_ID(0));
#else /* do not use PLL, use internal 8MHz oscillator directly */
    GCLK->GENDIV.reg =  (GCLK_GENDIV_DIV(CLOCK_DIV) |
                        GCLK_GENDIV_ID(0));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_SRC_OSC8M |
                         GCLK_GENCTRL_ID(0));
#endif

    /* make sure we synchronize clock generator 0 before we go on */
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}

    /* Setup Clock generator 2 with divider 1 (32.768kHz) */
    GCLK->GENDIV.reg  = (GCLK_GENDIV_ID(2)  | GCLK_GENDIV_DIV(0));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_GENEN |
            GCLK_GENCTRL_RUNSTDBY |
            GCLK_GENCTRL_SRC_OSCULP32K);

    while (GCLK->STATUS.bit.SYNCBUSY) {}

    /* redirect all peripherals to a disabled clock generator (7) by default */
    for (int i = 0x3; i <= 0x22; i++) {
        GCLK->CLKCTRL.reg = ( GCLK_CLKCTRL_ID(i) | GCLK_CLKCTRL_GEN_GCLK7 );
        while (GCLK->STATUS.bit.SYNCBUSY) {}
    }
}
Example #30
0
// Right now, PWM output only works on the pins with
// hardware support.  These are defined in the appropriate
// pins_*.c file.  For the rest of the pins, we default
// to digital output.
void analogWrite( uint32_t ulPin, uint32_t ulValue )
{
#if 0 // pwm test
#if 1 // port configuration
    *(volatile unsigned int *)0x44000010 |= 1 << 8;   //GPIOx->OUTENSET

    //PAD_AFConfig(PAD_PC, GPIO_Pin_8, 0x01/*PAD_AF1*/); ///< PAD Config - LED used 2nd Function	// (0x01 <<  8)
    *(volatile unsigned int *)(0x41002080 + 0x20) &= ~0x03/*PAD_AF1*/;	// (0x01 <<  8)
//    *(volatile unsigned int *)(0x41002080 + 0x20) |= 0x01/*PAD_AF1*/;	// (0x01 <<  8)

    *(volatile unsigned int *)0x44000010 |= 1 << 9;   //GPIOx->OUTENSET

    *(volatile unsigned int *)(0x41002080 + 0x24) &= ~0x03/*PAD_AF1*/;	// (0x01 <<  8)
//    *(volatile unsigned int *)(0x41002080 + 0x24) |= 0x01/*PAD_AF1*/;	// (0x01 <<  8)
#endif // port configuration
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
    /* Select Timer/Counter mode as Timer mode */ 
    //PWM_CHn->TCMR = PWM_CHn_TCMR_TimerMode;                      
//    *(volatile unsigned int *)0x40005324 = (0x0ul);  // ch3
    *(volatile unsigned int *)0x40005024 = (0x0);
    /* Set Prescale register value */
    //PWM_CHn->PR = PWM_TimerModeInitStruct->PWM_CHn_PR;        
//    *(volatile unsigned int *)0x40005314 = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    *(volatile unsigned int *)0x40005014 = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    /* Set Match register value */
    //PWM_CHn->MR = PWM_TimerModeInitStruct->PWM_CHn_MR;        
//    *(volatile unsigned int *)0x40005318 = 80000;
    *(volatile unsigned int *)0x40005018 = 80000;
    /* Set Limit register value */
    //PWM_CHn->LR = PWM_TimerModeInitStruct->PWM_CHn_LR;         
//    *(volatile unsigned int *)0x4000531C = 100000; // 80% duty cycle
    *(volatile unsigned int *)0x4000501C = 100000; // 80% duty cycle
    /* Select Up-down mode */
    //PWM_CHn->UDMR = PWM_TimerModeInitStruct->PWM_CHn_UDMR;     
//    *(volatile unsigned int *)0x40005320 = (0x0ul);        //PWM_CHn_UDMR_UpCount
    *(volatile unsigned int *)0x40005020 = (0x0);        //PWM_CHn_UDMR_UpCount
    /* Select Periodic mode */ 
    //PWM_CHn->PDMR = PWM_TimerModeInitStruct->PWM_CHn_PDMR;     
//    *(volatile unsigned int *)0x40005334 = (0x1ul);        //PWM_CHn_PDMR_Periodic
    *(volatile unsigned int *)0x40005034 = (0x1);        //PWM_CHn_PDMR_Periodic

//------------------------------------------------------------------------------------------
    /* Select Timer/Counter mode as Timer mode */ 
    //PWM_CHn->TCMR = PWM_CHn_TCMR_TimerMode;                      
//    *(volatile unsigned int *)0x40005324 = (0x0ul);  // ch3
    *(volatile unsigned int *)0x40005124 = (0x0ul);
    /* Set Prescale register value */
    //PWM_CHn->PR = PWM_TimerModeInitStruct->PWM_CHn_PR;        
//    *(volatile unsigned int *)0x40005314 = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    *(volatile unsigned int *)0x40005114 = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    /* Set Match register value */
    //PWM_CHn->MR = PWM_TimerModeInitStruct->PWM_CHn_MR;        
//    *(volatile unsigned int *)0x40005318 = 80000;
    *(volatile unsigned int *)0x40005118 = 80000;
    /* Set Limit register value */
    //PWM_CHn->LR = PWM_TimerModeInitStruct->PWM_CHn_LR;         
//    *(volatile unsigned int *)0x4000531C = 100000; // 80% duty cycle
    *(volatile unsigned int *)0x4000511C = 100000; // 80% duty cycle
    /* Select Up-down mode */
    //PWM_CHn->UDMR = PWM_TimerModeInitStruct->PWM_CHn_UDMR;     
//    *(volatile unsigned int *)0x40005320 = (0x0ul);        //PWM_CHn_UDMR_UpCount
    *(volatile unsigned int *)0x40005120 = (0x0ul);        //PWM_CHn_UDMR_UpCount
    /* Select Periodic mode */ 
    //PWM_CHn->PDMR = PWM_TimerModeInitStruct->PWM_CHn_PDMR;     
//    *(volatile unsigned int *)0x40005334 = (0x1ul);        //PWM_CHn_PDMR_Periodic
    *(volatile unsigned int *)0x40005134 = (0x1ul);        //PWM_CHn_PDMR_Periodic

//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
        //PWM->SSR &= PWM_SSR_SS3_Stop;
//        *(volatile unsigned int *)0x40005804 &= ~(0x1ul << 3);
        *(volatile unsigned int *)0x40005804 &= ~(0x1ul << 0);
        //PWM_CHn->PEEER = outputEnDisable; 
//        *(volatile unsigned int *)0x40005328 = (0x2ul);
        *(volatile unsigned int *)0x40005028 = (0x2ul);

//------------------------------------------------------------------------------------------
        //PWM->SSR &= PWM_SSR_SS3_Stop;
//        *(volatile unsigned int *)0x40005804 &= ~(0x1ul << 3);
        *(volatile unsigned int *)0x40005804 &= ~(0x1ul << 1);
        //PWM_CHn->PEEER = outputEnDisable; 
//        *(volatile unsigned int *)0x40005328 = (0x2ul);
        *(volatile unsigned int *)0x40005128 = (0x2ul);

//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------

        //PWM->SSR |= PWM_SSR_SS3_Start;
//        *(volatile unsigned int *)0x40005804 |= (0x1ul << 3);
        *(volatile unsigned int *)0x40005804 |= (0x1ul << 0);

//------------------------------------------------------------------------------------------
        //PWM->SSR |= PWM_SSR_SS3_Start;
//        *(volatile unsigned int *)0x40005804 |= (0x1ul << 3);
        *(volatile unsigned int *)0x40005804 |= (0x1ul << 1);




    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'P';
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'W';
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'M';
while(1);
#endif

#if 1
//------------------------------------------------------------------------------------------
    *(volatile unsigned int *)(0x42000010 + pwm_pin_tbl[ulPin].port_num) |= 1 << pwm_pin_tbl[ulPin].pin_num;   //GPIOx->OUTENSET
    //PAD_AFConfig(PAD_PC, GPIO_Pin_8, 0x01/*PAD_AF1*/); ///< PAD Config - LED used 2nd Function	// (0x01 <<  8)
    *(volatile unsigned int *)(0x41002000 + pwm_pin_tbl[ulPin].af_base + pwm_pin_tbl[ulPin].pin_num * 4) &= ~0x03/*PAD_AF1*/;	// (0x01 <<  8)
    *(volatile unsigned int *)(0x41002000 + pwm_pin_tbl[ulPin].af_base + pwm_pin_tbl[ulPin].pin_num * 4) |= pwm_pin_tbl[ulPin].af_num/*PAD_AF1*/;	// (0x01 <<  8)
//------------------------------------------------------------------------------------------
//PWM-n
    /* Select Timer/Counter mode as Timer mode */ 
    *(volatile unsigned int *)(0x40005024 + pwm_pin_tbl[ulPin].pwm_num) = (0x0);
    /* Set Prescale register value */
    *(volatile unsigned int *)(0x40005014 + pwm_pin_tbl[ulPin].pwm_num) = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    /* Set Match register value */
    *(volatile unsigned int *)(0x40005018 + pwm_pin_tbl[ulPin].pwm_num) = 400 * ulValue;     //MR
    /* Set Limit register value */
    *(volatile unsigned int *)(0x4000501C + pwm_pin_tbl[ulPin].pwm_num) = 102400; // 80% duty cycle
    /* Select Up-down mode */
    *(volatile unsigned int *)(0x40005020 + pwm_pin_tbl[ulPin].pwm_num) = (0x0);        //PWM_CHn_UDMR_UpCount
    /* Select Periodic mode */ 
    *(volatile unsigned int *)(0x40005034 + pwm_pin_tbl[ulPin].pwm_num) = (0x1);        //PWM_CHn_PDMR_Periodic

//------------------------------------------------------------------------------------------
        //PWM->SSR &= PWM_SSR_SS3_Stop;
        *(volatile unsigned int *)0x40005804 &= ~(0x1 << pwm_pin_tbl[ulPin].pwm_pin);
        //PWM_CHn->PEEER = outputEnDisable; 
        *(volatile unsigned int *)(0x40005028 + pwm_pin_tbl[ulPin].pwm_num) = 0x2;

//------------------------------------------------------------------------------------------
        //PWM->SSR |= PWM_SSR_SS3_Start;
        *(volatile unsigned int *)0x40005804 |= (0x1ul << pwm_pin_tbl[ulPin].pwm_pin);

#if 0  // pwm serial character out
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'P';
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'W';
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'M';
#endif  // pwm serial character out

#endif













#if 0
  uint32_t attr = g_APinDescription[ulPin].ulPinAttribute ;
//   uint32_t pwm_name = g_APinDescription[ulPin].ulTCChannel ;
  uint8_t isTC = 0 ;
  uint8_t Channelx ;
  Tc* TCx ;
  Tcc* TCCx ;

  if ( (attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG )
  {
    if ( ulPin == 24 )  // Only 1 DAC on A0 (PA02)
    {
      	ulValue = mapResolution(ulValue, _writeResolution, DAC_RESOLUTION);
    	DAC->DATA.reg = ulValue & 0x3FF;  // Dac on 10 bits.
		DAC->CTRLA.bit.ENABLE = 1; // DAC Enabled
/////////////////////////////////////		syncDAC();
      	return;
    }
	

  }

  if ( (attr & PIN_ATTR_PWM) == PIN_ATTR_PWM )
  {
    if ( (g_APinDescription[ulPin].ulPinType == PIO_TIMER) || g_APinDescription[ulPin].ulPinType == PIO_TIMER_ALT )
    {
      pinPeripheral( ulPin, g_APinDescription[ulPin].ulPinType ) ;
    }

    switch ( g_APinDescription[ulPin].ulPWMChannel )
    {
      case PWM3_CH0 :
                TCx = TC3 ;
                Channelx = 0 ;
                isTC = 1 ;
            break;

      case  PWM3_CH1:
                TCx = TC3 ;
                Channelx = 1;
                isTC = 1;
            break;

      case  PWM0_CH0 :
                TCCx = TCC0;
                Channelx = 0;
            break;

      case  PWM0_CH1 :
                TCCx = TCC0;
                Channelx = 1;
            break;

      case  PWM0_CH4 :
                TCCx = TCC0;
                Channelx = 0;
            break;

      case  PWM0_CH5 :
                TCCx = TCC0;
                Channelx = 1;
            break;

      case  PWM0_CH6 :
                TCCx = TCC0;
                Channelx = 2;
            break;

      case  PWM0_CH7 :
                TCCx = TCC0;
                Channelx = 3;
            break;

      case  PWM1_CH0 :
                TCCx = TCC1;
                Channelx = 0;
            break;

      case  PWM1_CH1 :
                TCCx = TCC1;
                Channelx = 1;
            break;

      case  PWM2_CH0 :
                TCCx = TCC2;
                Channelx = 0;
            break;

      case  PWM2_CH1 :
                TCCx = TCC2;
                Channelx = 1;
            break;
    }


    // Enable clocks according to TCCx instance to use
    switch ( GetTCNumber( g_APinDescription[ulPin].ulPWMChannel ) )
    {
      case 0: // TCC0
                //Enable GCLK for TCC0 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
            break;

      case 1: // TCC1
                //Enable GCLK for TCC1 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
            break;

      case 2: // TCC2
                //Enable GCLK for TCC2 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 )) ;
            break;

      case 3: // TC3
                //Enable GCLK for TC3 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 ));
            break;

      case 4: // TC4
                //Enable GCLK for TC4 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 ));
            break;

      case 5: // TC5
                //Enable GCLK for TC5 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 )) ;
            break;
    }

    // Set PORT
    if ( isTC )
    {
      // -- Configure TC
      //DISABLE TCx
      TCx->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE);
      //Set Timer counter Mode to 8 bits
      TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8;
      //Set TCx as normal PWM
      TCx->COUNT8.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM;
      //Set TCx in waveform mode Normal PWM
      TCx->COUNT8.CC[Channelx].reg = (uint8_t) ulValue;
      //Set PER to maximum counter value (resolution : 0xFF)
      TCx->COUNT8.PER.reg = 0xFF;
      // Enable TCx
      TCx->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
    }
    else
    {
      // -- Configure TCC

      //DISABLE TCCx
      TCCx->CTRLA.reg &=~(TCC_CTRLA_ENABLE);
      //Set TCx as normal PWM
      TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
      //Set TCx in waveform mode Normal PWM
      TCCx->CC[Channelx].reg = (uint32_t)ulValue;
      //Set PER to maximum counter value (resolution : 0xFF)
      TCCx->PER.reg = 0xFF;
      //ENABLE TCCx
      TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
    }

    return ;
  }

  // -- Defaults to digital write
  pinMode( ulPin, OUTPUT ) ;

  if ( ulValue < 128 )
  {
    digitalWrite( ulPin, LOW ) ;
  }
  else
  {
    digitalWrite( ulPin, HIGH ) ;
  }
#endif

}