forked from dllud/rr-avr-os
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtime.c
183 lines (160 loc) · 5.85 KB
/
time.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
* time.c
* Copyright (C) 2002-2011 Renato Jorge Caleira Nunes [email protected]
* Copyright (C) 2013 David Ludovino [email protected]
*
* System task which keeps track of time with the minimum granularity of 200 us.
* Allows the tracking of periods of 200 us, 1 ms, 10 ms, 50 ms, 100 ms, 1 s, 1 min, etc.
* In order to insert a timer one should declare it in the appropriate module header
* as an extern variable (check :cfg00) and then place it in the desired timing
* section (:cfg02), enabling the if macro. One must also activate the variable(s)
* needed to keep track of the period of time in use (:cfg01).
*
* This module uses Timer/Counter1 leaving 0 and 2 free for the pwm module.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License Version 3 as
* published by the Free Software Foundation.
*
* 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.
*/
/* Global includes */
#include "node.h"
/* Global includes for AVR */
#include <avr/io.h>
#include <avr/interrupt.h>
/* Specific inlucdes for this module */
#include "time.h"
/* Includes of the modules that use timers :cfg00 */
#include "led.h"
#include "digitalrw.h"
#include "pwm.h"
#include "usermods/example.h"
/* Local variables */
static uint8_t TIME_curr_time; /* incremented at each 200 us interruption */
static uint8_t TIME_last_time;
/* Initializes the timer. */
void TIME_init(void) {
/* Timer/Counter Control Register (p. 139)
* clock select: CLK/64 (16MHz/64=250KHZ -> 4us) */
TCCR1B = _BV(CS11) | _BV(CS10);
OCR1A = 50; /* 50 units of 4us (check above) = 200us */
/* Timer/Counter Interrupt Mask Register (p. 141)
* enable "Timer/Counter1 Compare Match A" interrupt */
TIMSK1 = _BV(OCIE1A);
}
/* Interruption "Compare Match A" handling routine (IHR) for timer 1.
* The declaration follows the directives for WinAVR and avr-gcc.
* An interruption is risen every 200 us (for a 16 MHz crystal). */
ISR(TIMER1_COMPA_vect) {
OCR1A += 50;
++TIME_curr_time;
}
#define TIME_1MS_N200US 5 /* 1 ms = 5 * 200 us */
#define TIME_10MS_N200US 50 /* 10 ms = 50 * 200 us */
#define TIME_50MS_N10MS 5 /* 50 ms = 5 * 10 ms */
#define TIME_100MS_N10MS 10 /* 100 ms = 10 * 10 ms */
#define TIME_1S_N10MS 100 /* 1 s = 100 * 10 ms */
#define TIME_1M_N1S 60 /* 1 min = 60 * 1 s */
/* Task which updates the variables from external modules which count time.
* These variables are called timers.
*
* Note that timers are updated in task time and not during interruption handling.
* If there is a need to count time in a piece of code which is in (infinite) cycle,
* for instance an active wait, the corresponding variable must be updated directly in the IHR.
*
* The base unit of time counting is 200 us. This modules also allows to count 1 ms,
* 10 ms, 50 ms, 100 ms, 1 s, and 1 min depending on the chosen configuration. */
void TIME_task(void) {
uint8_t elapsed_time; /* N * 200us */
static uint8_t t1ms_n200us = 0;
static uint8_t t10ms_n200us = 0;
static uint8_t t100ms_n10ms = 0;
static uint8_t t1s_n10ms = 0;
#if 0
/* Copy to above the necessary variables according to the time units you want
* to count. Notice that in order to have, for instace, 100 ms you need first
* the 10 ms variable. The 200 us unit is always available. :cfg01 */
static uint8_t t1ms_n200us = 0;
static uint8_t t10ms_n200us = 0;
static uint8_t t50ms_n10ms = 0;
static uint8_t t100ms_n10ms = 0;
static uint8_t t1s_n10ms = 0;
static uint8_t t1m_n1s = 0;
#endif
disable_interrupts; /* Check node.h */
elapsed_time = TIME_curr_time - TIME_last_time;
TIME_last_time = TIME_curr_time;
enable_interrupts; /* Check node.h */
/* Enable the needed sections bellow according to the time units you are tracking. */
/* 200 us timers
* var char: 1-255 => 0.2ms - 51.0ms (~0.05s)
* var int: 1-65535 => 0.2ms - 13107ms (~13s) */
#if 0
/*++MODULEXXX_timer; :cfg02*/
#endif
/* 1 ms timers
* var char: 1-255 => 1ms - 255ms (~0.25s)
* var int: 1-65535 => 1ms - 65535ms (~65.5s) */
#if 1
t1ms_n200us += elapsed_time;
if(t1ms_n200us >= TIME_1MS_N200US) {
t1ms_n200us -= TIME_1MS_N200US; /* 1 ms = 5 * 200 us */
++DIGITALRW_timer;
++PWM_timer;
/*++MODULEXXX_timer; :cfg02*/
}
#endif
/* 10 ms timers
* var char: 1-255 => 0.01s - 2.55s
* var int: 1-65535 => 0.01s - 655.35s (~10.9m) */
#if 1
t10ms_n200us += elapsed_time;
if(t10ms_n200us >= TIME_10MS_N200US) {
t10ms_n200us -= TIME_10MS_N200US; /* 10 ms = 50 * 200 us */
++LED_timer;
/*++MODULEXXX_timer; :cfg02*/
/* 50 ms timers (needs 10 ms)
* var char: 1-255 => 0.05s - 12.75s
* var int: 1-65535 => 0.05s - 3276.75s (~54.6m) */
#if 0
if(++t50ms_n10ms >= TIME_50MS_N10MS) {
t50ms_n10ms = 0; /* 50 ms = 5 * 10 ms */
/*++MODULEXXX_timer; :cfg02*/
}
#endif
/* 100 ms timers (needs 10 ms)
* var char: 1-255 => 0.1s - 25.5s
* var int: 1-65535 => 0.1s - 6553.5s (~109m, ~1.8h) */
#if 1
if(++t100ms_n10ms >= TIME_100MS_N10MS) {
t100ms_n10ms = 0; /* 100 ms = 10 * 10 ms */
++EXAMPLE_timer_pwm;
/*++MODULEXXX_timer; :cfg02*/
}
#endif
/* 1s timers (needs 10 ms)
* var char: 1-255 => 1s - 255s (~4.2m)
* var int: 1-65535 => 1s - 65535s (~1092m, ~18.2h) */
#if 1
if(++t1s_n10ms >= TIME_1S_N10MS) {
t1s_n10ms = 0; /* 1 s = 100 * 10 ms */
++EXAMPLE_timer_adc;
/*++MODULEXXX_timer; :cfg02*/
/* 1 min timers (needs 1 s)
* var char: 1-255 => 1m - 255m (~4.2h)
* var int: 1-65535 => 1m - 65535m (~1092h, ~45.5d) */
#if 0
if(++t1m_n1s >= TIME_1M_N1S) {
t1m_n1s = 0; /* 1 min = 60 * 1 s */
/*++MODULEXXX_timer; :cfg02*/
}
#endif
}
#endif /* 1 s timers */
}
#endif /* 10 ms timers */
}