Project

General

Profile

Statistics
| Revision:

root / branches / encoders / code / projects / libdragonfly / time.c @ 257

History | View | Annotate | Download (6.7 KB)

1 8 bcoltin
/*
2
time.c
3
anything that requires a delay
4
mostly delay_ms
5

6
author: Robotics Club, Colony Project
7

8
Change Log:
9
        2.5.07 - Kevin
10
                Aaron fixed the orb/servo code and made them use timer3 but compare registers B and C. He hard set the prescaler
11
                to 8 so the RTC broke. Changed it so that we use a 8 prescaler which sets the compare match at 1/16th of a second.
12
                You now count how many 16ths of a second you want until you trigger your actual interrupt. Works. Changed defines
13
                for time so you can still call rtc_init with a scale but now it is defined in terms of actual time like second, quarter_second
14
                etc. Read that section in the time.h file for more information. Tested and works, though the clock drifts more than
15
                it used to
16
        1.30.07 - Kevin
17
                Modified the clock to run on timer3 on the Dragonfly. Works with decent accuracy. Using a prescaler of 256
18
        the timer counts up to a precomputer value which will trigger an interrupt and reset the timer. Multiples of
19
        256 change it by that multiple. Refer to the time.h file for all possible prescalers.
20
                The interrupt will call a specified function _rtc_func every pulse.
21 184 ayeager
                All of it has been tested and it works.
22

23
        10.29.07 - Andrew
24
                Modify to accept multiple functions with different time intervals
25

26 8 bcoltin

27
*/
28
#include <avr/interrupt.h>
29
#include <util/delay.h>
30
#include <time.h>
31
#include <serial.h>
32
33
34 184 ayeager
35
static volatile int _rtc_val[MAX_FUNCTIONS];
36
static volatile int _rtc_pulse[MAX_FUNCTIONS];
37
static volatile int _rtc_scale[MAX_FUNCTIONS];
38
static int function_count = 0; //Number of functions
39 257 ayeager
static  void (*_rtc_f[MAX_FUNCTIONS])(void);
40 8 bcoltin
/**
41
 * @defgroup time Time
42
 * @brief Time functions
43
 *
44
 * Functions dealing with time.
45
 *
46
 * @{
47
 **/
48
49
/**
50
 * Delays for the specified number of milliseconds.
51
 * The accuracy of this function is unknown.
52
 *
53
 * @param ms the number of milliseconds to delay for
54
 **/
55
void delay_ms(int ms)
56
{
57
        for(; ms > 15; ms-=15)
58
                _delay_ms(15);
59
        _delay_ms(ms);
60
}
61
62
63
/*         Prescales defined in time.h. SECOND will give you 1 second.
64
        More scales are defined in the time.h file.
65
        rtc_func is the address to a function that you want called every clock tick. */
66
/**
67
 * Initializes the real time clock. Prescales are defined in time.h.
68
 * For example, SECOND will give 1 second. The specified function is
69
 * called every clock tick. For the real time clock to activate,
70
 * interrupts must be enabled. (through sei() )
71
 *
72
 * @param prescale_opt the period with which the timer is triggered
73
 * @param rtc_func the function called when the timer is triggered
74
 *
75
 * @see rtc_get, rtc_reset
76
 **/
77 184 ayeager
78
 int rtc_multi_init(int* prescale_opt,  void (*rtc_func[])(void), int argc) {
79 8 bcoltin
80 184 ayeager
        //Check that the number of functions doesn't exceed alloted space
81 193 ayeager
        if(argc > MAX_FUNCTIONS)
82 184 ayeager
                return -1;
83
84
        function_count = argc;
85 8 bcoltin
        //Clear timer register for Timer 3
86
        TCNT3 = 0;
87
88
        /*         This sets the Waveform Generation Module to CTC (Clear Timer on Compare) Mode (100)
89
                See page135 in Atmega128 Docs for more modes and explanations */
90
        TCCR3B |= _BV(WGM32);
91
92
        /*         This sets the prescaler for the system clock (8MHz) ie: divides the clock by some number.
93
                Currently set to a prescaler of 8 because that is what the orb and servos use (they are on this timer as well)
94
                See page137 in Atemga128 Docs for all the available prescalers */
95
        TCCR3B |= _BV(CS31);
96
97
        /*         Sets the two regsiters that we compare against. So the timer counts up to this number and
98
                then resets back to 0 and calls the compare match interrupt.
99
                8x10^6 / 8 = 1/16 Second. All values are based off of this number. Do not change it unless you
100
                are l337*/
101
102
        OCR3A = 0xF424;
103
104
        /*         Enable Output Compare A Interrupt. When OCR3A is met by the timer TCNT3 this interrupt will be
105
                triggerd. (See page140 in Atmega128 Docs for more information */
106
        ETIMSK |= _BV(OCIE3A);
107
108 184 ayeager
109
        /* Set number of functions*/
110
        function_count = argc;
111 8 bcoltin
112
        /*        Store how many 1/16ths of a second you want to let by before triggering an interrupt */
113 184 ayeager
114
        for (int i = 0; i <argc; i++) {
115
                _rtc_pulse[i] = 0;
116
                _rtc_val[i] = 0;
117
                _rtc_f[i] = rtc_func[i];
118
                /*        Store how many 1/16ths of a second you want to let by before triggering an interrupt */
119
                _rtc_scale[i] = prescale_opt[i];
120
        }
121
        return argc-1;
122 8 bcoltin
}
123
124 257 ayeager
int rtc_add_function(void (*rtc_func) (void), int prescale_opt)
125 184 ayeager
{
126 257 ayeager
        if(function_count>=MAX_FUNCTIONS)
127 184 ayeager
                return -1;
128
        _rtc_f[function_count] = rtc_func;
129
        _rtc_pulse[function_count] = 0;
130
        _rtc_scale[function_count]  = prescale_opt;
131 257 ayeager
        //return position in array that function was added to, increment count
132
        //this position may change if functions are removed
133
        return function_count++;
134 184 ayeager
}
135
136 257 ayeager
//remove function pointer
137
int rtc_remove_function(void (*rtc_func)(void))
138
{
139
        for(int i = 0; i < function_count; i++)
140
                if(_rtc_f[i] == rtc_func) {
141
                        //If not last function replace with last and reduce number of functions
142
                        if(i < function_count-1) {
143
                                _rtc_f[i] = _rtc_f[function_count-1];
144
                                _rtc_pulse[i] = _rtc_pulse[function_count-1];
145
                                _rtc_scale[i] = _rtc_scale[function_count-1];
146
                        }
147
                        return --function_count;
148
                }
149
150
        return -1;
151
}
152
153
int rtc_get_function_count()
154
{
155
        return function_count;
156
}
157
158
int rtc_init(int prescale_opt, void (*rtc_func)(void)){
159 184 ayeager
        int temp[] = {prescale_opt};
160
        void (*temp2[MAX_FUNCTIONS])(void) = {rtc_func};
161
        return rtc_multi_init(temp, temp2, 1);
162
}
163
164 8 bcoltin
/**
165
 * Returns the time elapsed in seconds since the last call to
166
 * rtc_init or rtc_reset.
167
 *
168
 * @return the number of seconds since the last call to rtc_init or rtc_reset
169
 *
170
 * @see rtc_init, rtc_reset
171
 **/
172 193 ayeager
173 8 bcoltin
int rtc_get(void){
174 193 ayeager
        return _rtc_val[0];
175
}
176 8 bcoltin
177 193 ayeager
int rtc_get_pos(int pos){
178
        return _rtc_val[pos];
179
}
180
181 8 bcoltin
/**
182
 * Resets the real time clock counter to 0.
183
 *
184
 * @see rtc_init, rtc_get
185
 **/
186 193 ayeager
187 8 bcoltin
void rtc_reset(void){
188 193 ayeager
        _rtc_val[0] = 0;
189
}
190 8 bcoltin
191 193 ayeager
void rtc_reset_all(void)
192
{
193 257 ayeager
        for(int i =0; i < function_count; i++)
194 193 ayeager
                _rtc_val[i] = 0;
195
}
196
197 8 bcoltin
/** @} **/ //end defgroup
198
199
/*        Called every pulse. Function in _rtc_f is called every _rtc_scale and also the counter is updated.
200
        Bascially, since the pulse is hard set at 1/16s  you want to count how many 16ths of a second have passed
201
        and when it reaches the amount of time you want, execute the code. */
202 184 ayeager
203 8 bcoltin
SIGNAL(TIMER3_COMPA_vect) {
204 184 ayeager
        for(int functionNumber = 0; functionNumber < function_count; functionNumber++)
205
        {
206
                if (_rtc_pulse[functionNumber] ==  _rtc_scale[functionNumber]) {
207
                        //Increment the real time clock counter
208
                        _rtc_val[functionNumber]++;
209
210
                        //Calls the function tied to the real time clock if defined
211
                        _rtc_f[functionNumber]();
212
213
                        //Resets the pulse until the next scale is matched
214
                        _rtc_pulse[functionNumber] = 0;
215
                }
216
                _rtc_pulse[functionNumber]++;
217
        }
218 8 bcoltin
        //Updates the amount of pulses seen since the last scale match
219
220
}