common.cpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #include "common.h"
  2. #include <avr/interrupt.h>
  3. #include <avr/io.h>
  4. void operator delete(void *, unsigned int) {}
  5. extern "C" void __cxa_pure_virtual() {}
  6. std::uint64_t gpt_system_tick = 0;
  7. void adjust_timer(const rotor_light::Duration &value) {
  8. gpt_system_tick += value;
  9. }
  10. rl::TimePoint get_now() {
  11. // The entire system-tick is composed of the static
  12. // 64-bit variable mcal_gpt_system_tick and the 8-bit
  13. // timer register TCNT0. These are concatenated together
  14. // in software as a cohesive, consistent 64-bit tick.
  15. // This subroutine returns the concatenated 64-bit
  16. // mcal_gpt_system_tick/TCNT0 64-bit system tick.
  17. // A multiple read of the tick is used in order
  18. // to ensure data consistency.
  19. // Do the first read of the TIMER0 counter and the system tick.
  20. const auto tim0_cnt_1 = TCNT0;
  21. const auto sys_tick_1 = gpt_system_tick;
  22. // Do the second read of the TIMER0 counter.
  23. const auto tim0_cnt_2 = TCNT0;
  24. // Perform the consistency check to obtain the concatenated,
  25. // consistent, 64-bit system-tick.
  26. const auto consistent_microsecond_tick =
  27. ((tim0_cnt_2 >= tim0_cnt_1)
  28. ? static_cast<std::uint64_t>(
  29. sys_tick_1 | static_cast<std::uint8_t>(tim0_cnt_1 >> 1U))
  30. : static_cast<std::uint64_t>(
  31. gpt_system_tick |
  32. static_cast<std::uint8_t>(tim0_cnt_2 >> 1U)));
  33. return consistent_microsecond_tick;
  34. }
  35. void enable_timer() {
  36. // We will now initialize the TIMER0 clock and interrupt.
  37. // Clear the TIMER0 overflow flag.
  38. TIFR0 = static_cast<std::uint8_t>(1U << TOV0);
  39. // Enable the TIMER0 overflow interrupt.
  40. TIMSK0 = static_cast<std::uint8_t>(1U << TOIE0);
  41. // Set the TIMER0 clock source to f_osc/8 = 2MHz and begin counting.
  42. TCCR0B = static_cast<std::uint8_t>(1U << CS01);
  43. }
  44. void disable_timer() {
  45. // erase TIMER0 clock source;
  46. TCCR0B = 0;
  47. // Clear the TIMER0 overflow flag.
  48. TIMSK0 = 0;
  49. // Enable the TIMER0 overflow interrupt.
  50. TIMSK0 = 0;
  51. }
  52. ISR(TIMER0_OVF_vect) {
  53. // Increment the 64-bit system tick with 0x80, representing 128 microseconds.
  54. gpt_system_tick += UINT8_C(0x80);
  55. }