You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.7KB

  1. // Copyright 2011 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. //
  16. // -----------------------------------------------------------------------------
  17. //
  18. // Clock configuration.
  19. #ifndef AVRLIBX_SYSTEM_CLOCK_H_
  20. #define AVRLIBX_SYSTEM_CLOCK_H_
  21. #include <avr/io.h>
  22. #include "avrlibx/avrlibx.h"
  23. #define CCP_WRITE(x, y) CCP = CCP_IOREG_gc; x = y;
  24. namespace avrlibx {
  25. enum ClockSource {
  26. CLOCK_INTERNAL_32M,
  27. CLOCK_EXTERNAL_8M,
  28. CLOCK_EXTERNAL_16M
  29. };
  30. template<ClockSource source, uint8_t pll_factor> void SetupClock() {
  31. if (source == CLOCK_INTERNAL_32M) {
  32. OSC.CTRL = OSC_RC32MEN_bm;
  33. while (!(OSC.STATUS & OSC_RC32MRDY_bm));
  34. if (pll_factor == 0) {
  35. CCP_WRITE(CLK.CTRL, CLK_SCLKSEL_RC32M_gc);
  36. } else {
  37. // The 32 Mhz RC oscillator has a base frequency of 8 MHz when fed to the
  38. // PLL.
  39. OSC.PLLCTRL = OSC_PLLSRC_RC32M_gc | (pll_factor << 2);
  40. }
  41. } else {
  42. if (source == CLOCK_EXTERNAL_8M) {
  43. OSC.XOSCCTRL = OSC_FRQRANGE_2TO9_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
  44. } else if (source == CLOCK_EXTERNAL_16M) {
  45. OSC.XOSCCTRL = OSC_FRQRANGE_2TO9_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
  46. }
  47. OSC.CTRL = OSC_XOSCEN_bm;
  48. while (!(OSC.STATUS & OSC_XOSCRDY_bm));
  49. if (pll_factor == 0) {
  50. CCP_WRITE(CLK.CTRL, CLK_SCLKSEL_XOSC_gc);
  51. } else {
  52. OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | pll_factor;
  53. }
  54. }
  55. if (pll_factor) {
  56. OSC.CTRL |= OSC_PLLEN_bm;
  57. while (!(OSC.STATUS & OSC_PLLRDY_bm));
  58. CCP_WRITE(CLK.CTRL, CLK_SCLKSEL_PLL_gc);
  59. }
  60. CCP_WRITE(CLK.PSCTRL, 0x00);
  61. }
  62. inline void SetupRTC() {
  63. CCP = CCP_IOREG_gc;
  64. CLK.RTCCTRL = CLK_RTCSRC_ULP_gc | CLK_RTCEN_bm;
  65. RTC.CTRL = RTC_PRESCALER_DIV1_gc;
  66. RTC.PER = 0xffff;
  67. RTC.CNT = 0;
  68. while(RTC.STATUS & RTC_SYNCBUSY_bm);
  69. }
  70. inline void SetupRTCMillisecondTick(uint8_t int_level) {
  71. CCP = CCP_IOREG_gc;
  72. CLK.RTCCTRL = CLK_RTCSRC_RCOSC_gc | CLK_RTCEN_bm;
  73. RTC.CTRL = RTC_PRESCALER_DIV1_gc;
  74. RTC.INTCTRL = int_level;
  75. RTC.PER = 100;
  76. RTC.CNT = 0;
  77. while(RTC.STATUS & RTC_SYNCBUSY_bm);
  78. }
  79. } // avrlibx
  80. #endif // AVRLIBX_SYSTEM_CLOCK_H_