Project

General

Profile

Revision 1345

Added by Rich Hong over 11 years ago

Final spline code for master/slave

updated outdated libdragonfly and libwireless

View differences:

time.c
1
/**
2
 * Copyright (c) 2007 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26

  
27
/**
28
 * @file time.c
29
 * @brief Timer code
30
 *
31
 * Implementation of functions for timers.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 **/
35

  
1 36
/*
2
time.c
3
anything that requires a delay
4
mostly delay_ms
37
  time.c
38
  anything that requires a delay
39
  mostly delay_ms
5 40

  
6
author: Robotics Club, Colony Project
41
  author: Robotics Club, Colony Project
7 42

  
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
	10.29.07 - Andrew
24
		Modify to accept multiple functions with different time intervals
25
	
43
  Change Log:
44
  2.5.07 - Kevin
45
  Aaron fixed the orb/servo code and made them use timer3 but compare registers B and C. He hard set the prescaler
46
  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.
47
  You now count how many 16ths of a second you want until you trigger your actual interrupt. Works. Changed defines
48
  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
49
  etc. Read that section in the time.h file for more information. Tested and works, though the clock drifts more than
50
  it used to
51
  1.30.07 - Kevin
52
  Modified the clock to run on timer3 on the Dragonfly. Works with decent accuracy. Using a prescaler of 256
53
  the timer counts up to a precomputer value which will trigger an interrupt and reset the timer. Multiples of
54
  256 change it by that multiple. Refer to the time.h file for all possible prescalers.
55
  The interrupt will call a specified function _rtc_func every pulse.
56
  All of it has been tested and it works.
26 57

  
27 58
*/
28 59
#include <avr/interrupt.h>
29 60
#include <util/delay.h>
30 61
#include <time.h>
31 62
#include <serial.h>
63

  
64
/* Calculate how many cycles to delay for to get 1 ms. Based on F_CPU which should be defined by the makefile */
65
#ifdef F_CPU
66
#define WAIT_CYCLES ((F_CPU / 1000) / 10)
67
#else
68
#define WAIT_CYCLES (8000 / 10)
69
#endif
32 70

  
71
static volatile int _rtc_val = 0;
72
static volatile int _rtc_pulse = 0;
73
static volatile int _rtc_scale = 32;	//Defaults to 1 Second per pulse
74
static void (*_rtc_f)(void) = 0;
75

  
76

  
33 77

  
34

  
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
static  void (*_rtc_f[MAX_FUNCTIONS])(void);
40 78
/**
41 79
 * @defgroup time Time
42 80
 * @brief Time functions
......
48 86

  
49 87
/**
50 88
 * Delays for the specified number of milliseconds.
51
 * The accuracy of this function is unknown.
89
 * It depends on F_CPU to be defined in order to calculate how many cycles
90
 * it should delay. If it is not defined, a default clock of 8MHz is assumed.
91
 * 
92
 * We use _delay_loop_2 which will run assembly instructions that should be
93
 * 4 cycles long. Optimizations must be enabled for this to be true.
94
 * That function is called to ensure around 1ms per execution. To generate
95
 * multiple ms we run a for loop of how many milliseconds are desired.
96
 *
97
 * The error should be just the skew on the oscillator as the formula to 
98
 * calculate delay cycles should always be a whole number. The is some skew
99
 * in practice though it is unavoidable. Delaying for less than 1s should make
100
 * the error negligable.
52 101
 *
53 102
 * @param ms the number of milliseconds to delay for
54 103
 **/
55
void delay_ms(int ms) 

56
{

57
	for(; ms > 15; ms-=15)

58
		_delay_ms(15);

59
	_delay_ms(ms);

60
}
104
void delay_ms(int ms) {
105
    for (; ms > 0; ms--) {
106
        _delay_loop_2(WAIT_CYCLES);
107
    }
108
}
109

  
61 110

  
62

  
63 111
/* 	Prescales defined in time.h. SECOND will give you 1 second.
64 112
	More scales are defined in the time.h file.
65 113
	rtc_func is the address to a function that you want called every clock tick. */
......
73 121
 * @param rtc_func the function called when the timer is triggered
74 122
 *
75 123
 * @see rtc_get, rtc_reset
124
 *
76 125
 **/
77
 
78
 int rtc_multi_init(int* prescale_opt,  void (*rtc_func[])(void), int argc) {
126
void rtc_init(int prescale_opt, void (*rtc_func)(void)) {
79 127
	
80
	//Check that the number of functions doesn't exceed alloted space
81
	if(argc > MAX_FUNCTIONS)
82
		return -1;
128
  //Clear timer register for Timer 3
129
  TCNT3 = 0;
83 130
	
84
	function_count = argc;
85
	//Clear timer register for Timer 3
86
	TCNT3 = 0;
131
  /* 	This sets the Waveform Generation Module to CTC (Clear Timer on Compare) Mode (100)
132
	See page135 in Atmega128 Docs for more modes and explanations */
133
  TCCR3B |= _BV(WGM32);
87 134
	
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);
135
  /* 	This sets the prescaler for the system clock (8MHz) ie: divides the clock by some number.
136
	Currently set to a prescaler of 8 because that is what the orb and servos use (they are on this timer as well)
137
	See page137 in Atemga128 Docs for all the available prescalers */
138
  TCCR3B |= _BV(CS31);
91 139
	
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*/
140
  /* 	Sets the two regsiters that we compare against. So the timer counts up to this number and
141
	then resets back to 0 and calls the compare match interrupt.
142
	8x10^6 / 8 = 1/16 Second. All values are based off of this number. Do not change it unless you
143
	are l337*/
101 144
		
102
	OCR3A = 0xF424;	
145
  OCR3A = 0xF424;	
103 146

  
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);
147
  /* 	Enable Output Compare A Interrupt. When OCR3A is met by the timer TCNT3 this interrupt will be
148
	triggerd. (See page140 in Atmega128 Docs for more information */
149
  ETIMSK |= _BV(OCIE3A);
107 150
	
108

  
109
	/* Set number of functions*/
110
	function_count = argc;
151
  /*	Store the pointer to the function to be used in the interrupt */
152
  _rtc_f = rtc_func;
111 153
	
112
	/*	Store how many 1/16ths of a second you want to let by before triggering an interrupt */
113
	
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;
154
  /*	Store how many 1/16ths of a second you want to let by before triggering an interrupt */
155
  _rtc_scale = prescale_opt;
122 156
}
123 157

  
124
int rtc_add_function(void (*rtc_func) (void), int prescale_opt)
125
{
126
	if(function_count>=MAX_FUNCTIONS)
127
		return -1;
128
	_rtc_f[function_count] = rtc_func;
129
	_rtc_pulse[function_count] = 0;
130
	_rtc_scale[function_count]  = prescale_opt;
131
	//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
}
135

  
136
//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
	int temp[] = {prescale_opt};
160
	void (*temp2[MAX_FUNCTIONS])(void) = {rtc_func};
161
	return rtc_multi_init(temp, temp2, 1);
162
}
163

  
164 158
/**
165 159
 * Returns the time elapsed in seconds since the last call to
166 160
 * rtc_init or rtc_reset.
......
169 163
 *
170 164
 * @see rtc_init, rtc_reset
171 165
 **/
172
 
173
int rtc_get(void){
174
	return _rtc_val[0];
166
int rtc_get(void) {
167
  return _rtc_val;
175 168
}
176 169

  
177
int rtc_get_pos(int pos){
178
	return _rtc_val[pos];
179
}
180

  
181 170
/**
182 171
 * Resets the real time clock counter to 0.
183 172
 *
184 173
 * @see rtc_init, rtc_get
185 174
 **/
186
 
187
void rtc_reset(void){
188
	_rtc_val[0] = 0;
175
void rtc_reset(void) {
176
  _rtc_val = 0;
189 177
}
190 178

  
191
void rtc_reset_all(void)
192
{
193
	for(int i =0; i < function_count; i++)
194
		_rtc_val[i] = 0;
195
}
196

  
197 179
/** @} **/ //end defgroup
198 180

  
199 181
/*	Called every pulse. Function in _rtc_f is called every _rtc_scale and also the counter is updated.
200 182
	Bascially, since the pulse is hard set at 1/16s  you want to count how many 16ths of a second have passed
201 183
	and when it reaches the amount of time you want, execute the code. */
184
SIGNAL(TIMER3_COMPA_vect) {
202 185

  
203
SIGNAL(TIMER3_COMPA_vect) {
204
	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
	//Updates the amount of pulses seen since the last scale match
186
  if (_rtc_pulse ==  _rtc_scale) {
187
    //Increment the real time clock counter
188
    _rtc_val++;
189
		
190
    //Calls the function tied to the real time clock if defined
191
    if(_rtc_f != 0)
192
      _rtc_f();
193
		
194
    //Resets the pulse until the next scale is matched
195
    _rtc_pulse = 0;
196
  }	
219 197
	
198
  //Updates the amount of pulses seen since the last scale match
199
  _rtc_pulse++;
200
	
220 201
}

Also available in: Unified diff