-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfancy_blink.c
110 lines (86 loc) · 2.19 KB
/
fancy_blink.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
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// prescaler is set so timer0 ticks every 64 clock cycles, and the overflow handler
// is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW \
(64UL * 256UL * 100000UL / ((F_CPU + 5UL) / 10UL))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000U)
// the fractional number of milliseconds per timer0 overflow
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000U) >> 3)
// shift right to fit in a byte
#define FRACT_MAX (1000U >> 3)
volatile unsigned long timer0_millis = 0;
volatile unsigned char timer0_fract = 0;
#if defined(__AVR_ATtiny13__) || defined(__AVR_ATtiny13A__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny85__)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// Copy to local vars so they can go in registers
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += MILLIS_INC + 1;
}
else {
m += MILLIS_INC;
}
timer0_millis = m;
timer0_fract = f;
}
void init_timer()
{
sei();
// Set timer0 prescaler to 64
#ifdef TCCR0B
TCCR0B |= _BV(CS01) | _BV(CS00);
#else
TCCR0 |= _BV(CS01) | _BV(CS00); // Atmega32a
#endif
// Set timer0 interrupt mask - TimerOverflowInterruptEnable
#ifdef TIMSK0
TIMSK0 |= _BV(TOIE0);
#else
TIMSK |= _BV(TOIE0); // Atmega32a
#endif
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// copy millis into 'm' atomically by disabling interrupts
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
int times[] = { 250, 250, 250, 1000, 50, 50, 50, 50, 50, 50, 50, 2000, 0 };
#define LEDPIN PB1
#define LEDDD DDB1
#define LEDDDR DDRB
#define LEDPORT PORTB
int main(void)
{
init_timer();
LEDDDR |= _BV(LEDDD);
LEDPORT = _BV(LEDPIN);
unsigned long lastTime = 0;
uint8_t t_index = 0;
for (;;) {
unsigned long currentTime = millis();
if (currentTime > lastTime + times[t_index]) {
LEDPORT ^= _BV(LEDPIN);
lastTime = currentTime;
t_index++;
if (!times[t_index])
t_index = 0;
}
// Do other stuff
}
return 0;
}