-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTime.c
208 lines (177 loc) · 5.86 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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include "Time.h"
#include <avr/interrupt.h>
static volatile uint8_t _timeTensOfMilliSeconds;
static volatile uint8_t _timeSeconds;
static volatile long _timeMinutes;
static uint8_t initializedAlreadyTimer = 0;
static float _clockSpeed;
float GetClockSpeed()
{
return _clockSpeed;
};
//set up using 8bit counter 0
void FullTimerInit(float clockSpeed)
{
if(initializedAlreadyTimer)
return;
_clockSpeed = clockSpeed;
initializedAlreadyTimer = 1;
_timeTensOfMilliSeconds = 0;
_timeSeconds = 0;
_timeMinutes = 0;
cli();
TCCR0A |= (1<<WGM01);//Timer/Counter Control Register |= (Clear Timer on Compare Match with OCRA & set TOV flag)
TIMSK0 |= (1 << OCIE0A);//enable interrupt comparing with OCROA
TCCR0B &= ~((1<<CS00) | (1<<CS01) | (1<<CS02));//clear any previously set values (TimerInit might be called to recalibrate the time after drift has occurred)
if(_clockSpeed == (float)1e6)
{
TCCR0B |= (1 << CS02);//prescale by 256
OCR0A = 39;//every 3,906.25 ticks make up a second
//we lose 0.0016 of a second every second, after 10min 25s we have lost a second (our clock is fast by a second)
}
else if(_clockSpeed == (float)16e6)
{
TCCR0B |= (1 << CS02) | (1<< CS00);//prescale by 1024
OCR0A = 156;//every 15,625 ticks make up a second
//we lose 0.0016 of a second every second, after 10min 25s we have lost a second (our clock is fast by a second)
}
else if(_clockSpeed == (float)14.7456e6)
{
TCCR0B |= (1 << CS02) | (1<< CS00);//prescale by 1024
OCR0A = 144;//every 14,400 ticks make up a second
//we lose nothing, the clock is accurate
}
else if(_clockSpeed == (float)12.288e6)
{
TCCR0B |= (1 << CS02) | (1<< CS00);//prescale by 1024
OCR0A = 120;//every 12000 ticks make up a second
//we lose nothing, the clock is accurate
}
TCNT0 = 0;
// enable global interrupts
sei();
};
long GetTotalTimerValueInMilliSeconds()
{
cli();
long time = (_timeMinutes*60*1000)+(_timeSeconds*1000)+(_timeTensOfMilliSeconds*10);
sei();
return time;
};
long GetTimerValue(enum TimeUnits timeUnit)
{
cli();
long returnValue = 0;
switch(timeUnit)
{
case TensOfMilliSeconds:
returnValue = _timeTensOfMilliSeconds;
break;
case Seconds:
returnValue = _timeSeconds;
break;
case Minutes:
returnValue = _timeMinutes;
break;
default:
break;
}
sei();
return returnValue;
};
ISR(TIMER0_COMPA_vect)
{
cli();
++_timeTensOfMilliSeconds;
if(_timeTensOfMilliSeconds >= 100)
{
_timeTensOfMilliSeconds = 0;
++_timeSeconds;
if(_timeSeconds >= 60)
{
_timeSeconds = 0;
++_timeMinutes;
}
}
sei();
};
void DelayInit(float clockspeed)
{
_clockSpeed = clockspeed;
}
//use counter 1 which is 16bit
//This will not have very good results with a clock slower than 10Mhz
//and is only useful for rough estimates. For small wait times, it is useless.
void DelayMicroseconds(int numberOfMicroseconds)
{
TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10));//clear any previously set flags
float numberOfTicksToWait = 0;
int numberOfTicksConsumedinSetup = 14;
if(_clockSpeed == (float)1e6)
{//at 1,000,000 ticks per second, there is 1 tick per uS
numberOfTicksToWait = numberOfMicroseconds;
}
else if(_clockSpeed == (float)16e6)
{//at 16,000,000 ticks per second, there are 16 ticks per uS
numberOfTicksToWait = numberOfMicroseconds*16;
numberOfTicksConsumedinSetup++;
}
else if(_clockSpeed == (float)14.7456e6)
{//14,745,600 ticks per second, there are 14.7456 ticks per uS
numberOfTicksToWait = numberOfMicroseconds * (float)14.7456;
numberOfTicksConsumedinSetup +=2;
}
else if(_clockSpeed == (float)12.288e6)
{//12,288,000 ticks per second, there are 12.288 ticks per uS
numberOfTicksToWait = numberOfMicroseconds * (float)12.288e6;
numberOfTicksConsumedinSetup +=3;
}
//TCNT1 is 2bytes in size
TCNT1 = 0; // Reset timer value
//I estimate that it has taken x ticks to get up to this point, and will take a tick to get back to the calling code
while(TCNT1 < (numberOfTicksToWait - numberOfTicksConsumedinSetup))
{}
};
//use counter 1 which is 16bit
void DelayMilliseconds(int numberOfMilliseconds)//up to 4.1 seconds
{
TCCR1B &= ~((1<<CS12)|(1<<CS11)| (1<<CS10));//clear any previously set flags
float numberOfTicksToWait = 0;
if(_clockSpeed == (float)1e6)
{//at 1,000,000 ticks per second, there are 1,000 ticks per milliSecond
//if we prescale by 64 then every 15.625ticks is equal to a milliSecond
//the max value that TCNT1 can hold is 65,536 the max delay is therefore 4194.304 seconds
TCCR1B = (1 << CS11) | (1 << CS10);
numberOfTicksToWait = 15.625*numberOfMilliseconds;
}
else if(_clockSpeed == (float)16e6)
{//at 16,000,000 ticks per second, there are 16,000 ticks per milliSecond
//if we prescale by 1024 then every 15.625ticks is equal to a milliSecond
//the max value that TCNT1 can hold is 65,536 the max delay is therefore 4194.304 seconds
TCCR1B = (1 << CS12)| (1<<CS10);
numberOfTicksToWait = 15.625*numberOfMilliseconds;
}
else if(_clockSpeed == (float)14.7456e6)
{//14,745,600 ticks per second, there are 14,745.6 ticks per milliSecond
//if we prescale by 1024 then every 14.4ticks is equal to a milliSecond
//the max value that TCNT1 can hold is 65,536 the max delay is therefore 4551.111seconds
TCCR1B = (1 << CS12) | (1<<CS10);
numberOfTicksToWait = 14.4*numberOfMilliseconds;
}
else if(_clockSpeed == (float)12.288e6)
{//12,288,000 ticks per second, there are 12,288 ticks per milliSecond
//if we prescale by 1024 then every 12ticks is equal to a milliSecond
//the max value that TCNT1 can hold is 65,536 the max delay is therefore 5461.333 seconds
TCCR1B = (1 << CS12)| (1<<CS10);
numberOfTicksToWait = 12*numberOfMilliseconds;
}
//TCNT1 is 2bytes in size
TCNT1 = 0; // Reset timer value
while(TCNT1 < numberOfTicksToWait)
{}
};
//use counter 1 which is 16bit
void DelaySeconds(int numberOfSeconds)//up to 16 seconds
{
for(int i = 0; i < numberOfSeconds; ++i){DelayMilliseconds(1000);}
};