YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
timer_rp2040.cpp
1/*
2 * timer_rp2040.cpp
3 *
4 * Created on: 01.11.2022
5 * Author: aterstegge
6 */
7
8#include "timer_rp2040.h"
9#include "system_rp2040.h"
10#include "task.h"
11#include <cassert>
12
13timer_rp2040 * timer_rp2040::_timerinst[4];
14function<void()> timer_rp2040::_callback[4];
15
16timer_rp2040::timer_rp2040(int8_t index) {
17 if (index == -1) {
18 // Find next free timer
19 for (index=0; index < 4; ++index) {
20 if (!_timerinst[index]) break;
21 }
22 }
23 assert(index < 4);
24 assert(_timerinst[index] == nullptr);
25 // Initialize members
26 _index = index;
27 _mask = 1 << index;
28 _ALARM = &(_TIMER_::TIMER.ALARM0) + index;
29 _mode = TIMER::ONE_SHOT;
30 _period = 0;
31 // Calculate factor
32 _tick_factor= CLK_TICK / 1000000;
33 // Register timer instance pointer
34 _timerinst[index] = this;
35 // Enable timer interrupt
36 _TIMER_::TIMER_SET.INTE = _mask;
37 // enable IRQ in NVIC. Default priority is 0 (highest).
38 NVIC_EnableIRQ(IRQn_Type(TIMER_IRQ_0_IRQn + index));
39}
40
41timer_rp2040::~timer_rp2040() {
42 stop();
43 _timerinst[_index] = nullptr;
44}
45
46void timer_rp2040::setPeriod(uint32_t us, TIMER::timer_mode mode) {
47 _period = us * _tick_factor;
48 _mode = mode;
49}
50
51void timer_rp2040::setPeriod_ns(uint32_t ns, TIMER::timer_mode mode) {
52 _period = (ns * _tick_factor) / 1000;
53 _mode = mode;
54}
55
56uint32_t timer_rp2040::getPeriod() {
57 return _period / _tick_factor;
58}
59
60void timer_rp2040::setCallback(function<void()> f) {
61 timer_rp2040::_callback[_index] = f;
62}
63
64void timer_rp2040::start() {
65 *_ALARM = _TIMER_::TIMER.TIMERAWL + _period;
66}
67
68void timer_rp2040::stop() {
69 if (isRunning()) {
70 // Clear 'armed'-bit
71 _TIMER_::TIMER.ARMED = _mask;
72 }
73}
74
75bool timer_rp2040::isRunning() {
76 return _TIMER_::TIMER.ARMED & _mask;
77}
78
79void timer_rp2040::reset() {
80 // If timer is running, immediately
81 // trigger a re-start.
82 if (isRunning()) start();
83}
84
85void timer_rp2040::irqHandler() {
86 // Clear interrupt
87 _TIMER_::TIMER.INTR = _mask;
88 // Re-trigger timer if periodic
89 if (_mode == TIMER::PERIODIC) {
90 *_ALARM += _period;
91 }
92 // Call the user-provided handler
93 _callback[_index]();
94}
95
96// Interrupt handler
98extern "C" {
99
100void TIMER_IRQ_0_Handler(void) {
101 timer_rp2040::_timerinst[0]->irqHandler();
102}
103
104void TIMER_IRQ_1_Handler(void) {
105 timer_rp2040::_timerinst[1]->irqHandler();
106}
107
108void TIMER_IRQ_2_Handler(void) {
109 timer_rp2040::_timerinst[2]->irqHandler();
110}
111
112void TIMER_IRQ_3_Handler(void) {
113 timer_rp2040::_timerinst[3]->irqHandler();
114}
115
116} // extern "C"