Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / colonet / utilities / robot_slave / time.c @ 13

History | View | Annotate | Download (4.12 KB)

1
/*
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
                All of it has been tested and it works.
22

23
*/
24
#include <avr/interrupt.h>
25
#include <util/delay.h>
26
#include <time.h>
27
#include <serial.h>
28

    
29
static volatile int _rtc_val = 0;
30
static volatile int _rtc_pulse = 0;
31
static volatile int _rtc_scale = 32;        //Defaults to 1 Second per pulse
32
static void (*_rtc_f)(void) = 0;
33

    
34
/*
35
delay_ms
36

37
delays for ms milliseconds
38

39
accuracy is unknown (off by tens of nanoseconds every 15 ms)
40
*/
41
void delay_ms(int ms) 
42
{
43
        for(; ms > 15; ms-=15)
44
                _delay_ms(15);
45
        _delay_ms(ms);
46
}
47

    
48
void pause_ms(int ms)
49
{
50
        delay_ms(ms);
51
}
52

    
53
void pause(int ms)
54
{
55
        delay_ms(ms);
56
}
57

    
58
void sleep_ms(int ms)
59
{
60
        delay_ms(ms);
61
}
62

    
63
void sleep(int ms)
64
{
65
        delay_ms(ms);
66
}
67

    
68
/*         Prescales defined in time.h. SECOND will give you 1 second.
69
        More scales are defined in the time.h file.
70
        rtc_func is the address to a function that you want called every clock tick. */
71
void rtc_init(int prescale_opt, void (*rtc_func)(void)) {
72
        
73
        //Clear timer register for Timer 3
74
        TCNT3 = 0;
75
        
76
        /*         This sets the Waveform Generation Module to CTC (Clear Timer on Compare) Mode (100)
77
                See page135 in Atmega128 Docs for more modes and explanations */
78
        TCCR3B |= _BV(WGM32);
79
        
80
        /*         This sets the prescaler for the system clock (8MHz) ie: divides the clock by some number.
81
                Currently set to a prescaler of 8 because that is what the orb and servos use (they are on this timer as well)
82
                See page137 in Atemga128 Docs for all the available prescalers */
83
        TCCR3B |= _BV(CS31);
84
        
85
        /*         Sets the two regsiters that we compare against. So the timer counts up to this number and
86
                then resets back to 0 and calls the compare match interrupt.
87
                8x10^6 / 8 = 1/16 Second. All values are based off of this number. Do not change it unless you
88
                are l337*/
89
                
90
        OCR3A = 0xF424;        
91

    
92
        /*         Enable Output Compare A Interrupt. When OCR3A is met by the timer TCNT3 this interrupt will be
93
                triggerd. (See page140 in Atmega128 Docs for more information */
94
        ETIMSK |= _BV(OCIE3A);
95
        
96
        /*        Store the pointer to the function to be used in the interrupt */
97
        _rtc_f = rtc_func;
98
        
99
        /*        Store how many 1/16ths of a second you want to let by before triggering an interrupt */
100
        _rtc_scale = prescale_opt;
101
}
102

    
103
//Returns the real time clock counter to 0
104
int rtc(void){
105
        return _rtc_val;
106
}
107

    
108
//Resets the real time clock counter
109
void rtc_reset(void){
110
        _rtc_val = 0;
111
}
112

    
113
/*        Called every pulse. Function in _rtc_f is called every _rtc_scale and also the counter is updated.
114
        Bascially, since the pulse is hard set at 1/16s  you want to count how many 16ths of a second have passed
115
        and when it reaches the amount of time you want, execute the code. */
116
SIGNAL(TIMER3_COMPA_vect) {
117

    
118
        if (_rtc_pulse ==  _rtc_scale) {
119
                //Increment the real time clock counter
120
                _rtc_val++;
121
                
122
                //Calls the function tied to the real time clock if defined
123
                if(_rtc_f != 0)
124
                        _rtc_f();
125
                
126
                //Resets the pulse until the next scale is matched
127
                _rtc_pulse = 0;
128
        }        
129
        
130
        //Updates the amount of pulses seen since the last scale match
131
        _rtc_pulse++;
132
        
133
}
134