summaryrefslogtreecommitdiff
path: root/trunk/darwin/firmware/Arduino/GCode_Interpreter_Experimental/timer1_interrupt_routines.pde
blob: 341e9999d22bea3674cc554540fff79bd2e23672 (plain)
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
//these routines provide an easy interface for controlling timer1 interrupts

//this handles the timer interrupt event
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
	extruder_error--;
}

void enableTimer1Interrupt()
{
	//enable our interrupt!
	TIMSK1 |= (1<<OCIE1A);
}

void disableTimer1Interrupt()
{
	TIMSK1 &= ~(1<<ICIE1);
	TIMSK1 &= ~(1<<OCIE1A);
}

void setTimer1Resolution(byte r)
{
	//from table 15-5 in that atmega168 datasheet:
	// we're setting CS12 - CS10 which correspond to the binary numbers 0-5
	// 0 = no timer
	// 1 = no prescaler
	// 2 = clock/8
	// 3 = clock/64
	// 4 = clock/256
	// 5 = clock/1024
	
	if (r > 5)
		r = 5;
		
	TCCR1B &= B11111000;
	TCCR1B |= r;
}

void setTimer1Ceiling(unsigned int c)
{
	OCR1A = c;
}


unsigned int getTimer1Ceiling(unsigned long ticks)
{
	// our slowest speed at our highest resolution ( (2^16-1) * 0.0625 usecs = 4095 usecs)
	if (ticks <= 65535L)
		return (ticks & 0xffff);
	// our slowest speed at our next highest resolution ( (2^16-1) * 0.5 usecs = 32767 usecs)
	else if (ticks <= 524280L)
		return ((ticks / 8) & 0xffff);
	// our slowest speed at our medium resolution ( (2^16-1) * 4 usecs = 262140 usecs)
	else if (ticks <= 4194240L)
		return ((ticks / 64) & 0xffff);
	// our slowest speed at our medium-low resolution ( (2^16-1) * 16 usecs = 1048560 usecs)
	else if (ticks <= 16776960L)
		return (ticks / 256);
	// our slowest speed at our lowest resolution ((2^16-1) * 64 usecs = 4194240 usecs)
	else if (ticks <= 67107840L)
		return (ticks / 1024);
	//its really slow... hopefully we can just get by with super slow.
	else
		return 65535;
}

byte getTimer1Resolution(unsigned long ticks)
{
	// these also represent frequency: 1000000 / ticks / 2 = frequency in hz.
	
	// our slowest speed at our highest resolution ( (2^16-1) * 0.0625 usecs = 4095 usecs (4 millisecond max))
	// range: 8Mhz max - 122hz min
	if (ticks <= 65535L)
		return 1;
	// our slowest speed at our next highest resolution ( (2^16-1) * 0.5 usecs = 32767 usecs (32 millisecond max))
	// range:1Mhz max - 15.26hz min
	else if (ticks <= 524280L)
		return 2;
	// our slowest speed at our medium resolution ( (2^16-1) * 4 usecs = 262140 usecs (0.26 seconds max))
	// range: 125Khz max - 1.9hz min
	else if (ticks <= 4194240L)
		return 3;
	// our slowest speed at our medium-low resolution ( (2^16-1) * 16 usecs = 1048560 usecs (1.04 seconds max))
	// range: 31.25Khz max - 0.475hz min
	else if (ticks <= 16776960L)
		return 4;
	// our slowest speed at our lowest resolution ((2^16-1) * 64 usecs = 4194240 usecs (4.19 seconds max))
	// range: 7.812Khz max - 0.119hz min
	else if (ticks <= 67107840L)
		return 5;
	//its really slow... hopefully we can just get by with super slow.
	else
		return 5;
}

void setTimer1Ticks(unsigned long ticks)
{
	// ticks is the delay between interrupts in 4 microsecond ticks.
	//
	// we break it into 5 different resolutions based on the delay. 
	// then we set the resolution based on the size of the delay.
	// we also then calculate the timer ceiling required. (ie what the counter counts to)
	// the result is the timer counts up to the appropriate time and then fires an interrupt.

	setTimer1Ceiling(getTimer1Ceiling(ticks));
	setTimer1Resolution(getTimer1Resolution(ticks));
}

void setupTimer1Interrupt()
{
	//clear the registers
	TCCR1A = 0;
	TCCR1B = 0;
	TCCR1C = 0;
	TIMSK1 = 0;
	
	//waveform generation = 0100 = CTC
	TCCR1B &= ~(1<<WGM13);
	TCCR1B |=  (1<<WGM12);
	TCCR1A &= ~(1<<WGM11); 
	TCCR1A &= ~(1<<WGM10);

	//output mode = 00 (disconnected)
	TCCR1A &= ~(1<<COM1A1); 
	TCCR1A &= ~(1<<COM1A0);
	TCCR1A &= ~(1<<COM1B1); 
	TCCR1A &= ~(1<<COM1B0);

	//start off with a slow frequency.
	setTimer1Resolution(5);
	setTimer1Ceiling(65535);
	disableTimer1Interrupt();
}