forked from baocang/chlib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimer3.c
97 lines (84 loc) · 2.14 KB
/
timer3.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Copyright 2021 Takashi Toyoshima <[email protected]>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "timer3.h"
#include "io.h"
static uint16_t timer3_tick = 0;
void timer3_int() __interrupt INT_NO_TMR3 __using 1 {
timer3_tick++;
T3_STAT |= bT3_IF_END;
}
static bool timer3_tick_ge(uint16_t tick) {
uint8_t h = tick >> 8;
uint8_t t = T3_COUNT_H;
if (t < h)
return false;
if (t > h)
return true;
uint8_t l = tick;
t = T3_COUNT_L;
if (t >= l)
return true;
return T3_COUNT_H > h;
}
static bool timer3_tick_le(uint16_t tick) {
uint8_t h = tick >> 8;
uint8_t t = T3_COUNT_H;
if (t > h)
return false;
if (t < h)
return true;
uint8_t l = tick;
t = T3_COUNT_L;
if (t > l)
return false;
return T3_COUNT_H <= h;
}
void timer3_tick_init() {
T3_SETUP |= bT3_EN_CK_SE; // Enable to access divisor settings register
T3_CK_SE_L = 0x80; // Clock = Fsys(48M) / 48k = 1kHz
T3_CK_SE_H = 0xbb;
T3_SETUP &= ~bT3_EN_CK_SE; // Disable
T3_END_L = 0x70;
T3_END_H = 0x3e; // 1000 * 16
T3_CTRL |= bT3_CLR_ALL;
T3_CTRL &= ~bT3_CLR_ALL;
T3_SETUP |= bT3_IE_END; // Enable end interrupt
T3_CTRL |= bT3_CNT_EN; // Start counting
T3_STAT = 0xff;
IE_TMR3 = 1; // Enable timer3 interrupt
EA = 1; // Enable interruprts
}
uint16_t timer3_tick_raw() {
uint16_t tick;
for (;;) {
uint8_t h = T3_COUNT_H;
uint8_t l = T3_COUNT_L;
if (h == T3_COUNT_H) {
tick = (h << 8) | l;
break;
}
}
return tick;
}
uint16_t timer3_tick_from_usec(uint16_t usec) {
uint16_t x16 = usec * 16;
uint16_t tick = x16 / 1000;
if (x16 % 1000)
tick++;
return tick;
}
uint16_t timer3_tick_msec() {
return timer3_tick_raw() >> 4;
}
uint16_t timer3_tick_sec() {
return timer3_tick;
}
bool timer3_tick_raw_between(uint16_t begin, uint16_t end) {
if (begin < end)
return timer3_tick_ge(begin) && timer3_tick_le(end);
return timer3_tick_ge(begin) || timer3_tick_le(end);
}
bool timer3_tick_msec_between(uint16_t begin, uint16_t end) {
return timer3_tick_raw_between(begin << 4, end << 4);
}