// Copyright 2011 Olivier Gillet. // // Author: Olivier Gillet (ol.gillet@gmail.com) // // 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 3 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 . // // ----------------------------------------------------------------------------- // // Clock configuration. #ifndef AVRLIBX_SYSTEM_CLOCK_H_ #define AVRLIBX_SYSTEM_CLOCK_H_ #include #include "avrlibx/avrlibx.h" #define CCP_WRITE(x, y) CCP = CCP_IOREG_gc; x = y; namespace avrlibx { enum ClockSource { CLOCK_INTERNAL_32M, CLOCK_EXTERNAL_8M, CLOCK_EXTERNAL_16M }; template void SetupClock() { if (source == CLOCK_INTERNAL_32M) { OSC.CTRL = OSC_RC32MEN_bm; while (!(OSC.STATUS & OSC_RC32MRDY_bm)); if (pll_factor == 0) { CCP_WRITE(CLK.CTRL, CLK_SCLKSEL_RC32M_gc); } else { // The 32 Mhz RC oscillator has a base frequency of 8 MHz when fed to the // PLL. OSC.PLLCTRL = OSC_PLLSRC_RC32M_gc | (pll_factor << 2); } } else { if (source == CLOCK_EXTERNAL_8M) { OSC.XOSCCTRL = OSC_FRQRANGE_2TO9_gc | OSC_XOSCSEL_XTAL_16KCLK_gc; } else if (source == CLOCK_EXTERNAL_16M) { OSC.XOSCCTRL = OSC_FRQRANGE_2TO9_gc | OSC_XOSCSEL_XTAL_16KCLK_gc; } OSC.CTRL = OSC_XOSCEN_bm; while (!(OSC.STATUS & OSC_XOSCRDY_bm)); if (pll_factor == 0) { CCP_WRITE(CLK.CTRL, CLK_SCLKSEL_XOSC_gc); } else { OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | pll_factor; } } if (pll_factor) { OSC.CTRL |= OSC_PLLEN_bm; while (!(OSC.STATUS & OSC_PLLRDY_bm)); CCP_WRITE(CLK.CTRL, CLK_SCLKSEL_PLL_gc); } CCP_WRITE(CLK.PSCTRL, 0x00); } inline void SetupRTC() { CCP = CCP_IOREG_gc; CLK.RTCCTRL = CLK_RTCSRC_ULP_gc | CLK_RTCEN_bm; RTC.CTRL = RTC_PRESCALER_DIV1_gc; RTC.PER = 0xffff; RTC.CNT = 0; while(RTC.STATUS & RTC_SYNCBUSY_bm); } inline void SetupRTCMillisecondTick(uint8_t int_level) { CCP = CCP_IOREG_gc; CLK.RTCCTRL = CLK_RTCSRC_RCOSC_gc | CLK_RTCEN_bm; RTC.CTRL = RTC_PRESCALER_DIV1_gc; RTC.INTCTRL = int_level; RTC.PER = 100; RTC.CNT = 0; while(RTC.STATUS & RTC_SYNCBUSY_bm); } } // avrlibx #endif // AVRLIBX_SYSTEM_CLOCK_H_