/* * Copyright (c) 2014-2017, Alex Taradov * All rights reserved. * * 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 the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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. */ //----------------------------------------------------------------------------- #include #include #include #include #include "saml22.h" #include "hal_gpio.h" //----------------------------------------------------------------------------- #define PERIOD_FAST 100 #define PERIOD_SLOW 500 HAL_GPIO_PIN(LED, A, 21) HAL_GPIO_PIN(BUTTON, A, 30) HAL_GPIO_PIN(UART_TX, A, 22) HAL_GPIO_PIN(UART_RX, A, 23) //----------------------------------------------------------------------------- static void timer_set_period(uint16_t i) { TC3->COUNT16.CC[0].reg = (F_CPU / 1000ul / 256) * i; TC3->COUNT16.COUNT.reg = 0; } //----------------------------------------------------------------------------- void irq_handler_tc3(void) { if (TC3->COUNT16.INTFLAG.reg & TC_INTFLAG_MC(1)) { HAL_GPIO_LED_toggle(); TC3->COUNT16.INTFLAG.reg = TC_INTFLAG_MC(1); } } //----------------------------------------------------------------------------- static void timer_init(void) { MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC3; GCLK->PCHCTRL[TC3_GCLK_ID].reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN; while (0 == (GCLK->PCHCTRL[TC3_GCLK_ID].reg & GCLK_PCHCTRL_CHEN)); TC3->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_PRESCALER(6/*DIV256*/) | TC_CTRLA_PRESCSYNC_RESYNC; TC3->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ; TC3->COUNT16.COUNT.reg = 0; timer_set_period(PERIOD_SLOW); TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; TC3->COUNT16.INTENSET.reg = TC_INTENSET_MC(1); NVIC_EnableIRQ(TC3_IRQn); } //----------------------------------------------------------------------------- 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(HAL_GPIO_PMUX_C); HAL_GPIO_UART_RX_in(); HAL_GPIO_UART_RX_pmuxen(HAL_GPIO_PMUX_C); MCLK->APBCMASK.reg |= MCLK_APBCMASK_SERCOM0; GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN; while (0 == (GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg & GCLK_PCHCTRL_CHEN)); SERCOM0->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE(1/*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; SERCOM0->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; } //----------------------------------------------------------------------------- static void uart_putc(char c) { while (!(SERCOM0->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)); SERCOM0->USART.DATA.reg = c; } //----------------------------------------------------------------------------- static void uart_puts(char *s) { while (*s) uart_putc(*s++); } //----------------------------------------------------------------------------- static void sys_init(void) { // Switch to 16MHz clock (disable prescaler) OSCCTRL->OSC16MCTRL.reg = OSCCTRL_OSC16MCTRL_ENABLE | OSCCTRL_OSC16MCTRL_FSEL_16; // Switch to the highest performance level PM->INTFLAG.reg = PM_INTFLAG_PLRDY; PM->PLCFG.reg = PM_PLCFG_PLSEL_PL2_Val; while (!PM->INTFLAG.reg); } //----------------------------------------------------------------------------- int main(void) { uint32_t cnt = 0; bool fast = false; sys_init(); timer_init(); uart_init(115200); uart_puts("\r\nHello, world!\r\n"); HAL_GPIO_LED_out(); HAL_GPIO_LED_clr(); HAL_GPIO_BUTTON_in(); HAL_GPIO_BUTTON_pullup(); while (1) { if (HAL_GPIO_BUTTON_read()) cnt = 0; else if (cnt < 5001) cnt++; if (5000 == cnt) { fast = !fast; timer_set_period(fast ? PERIOD_FAST : PERIOD_SLOW); uart_putc('.'); } } return 0; }