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