File: isrs.S

package info (click to toggle)
avr-libc 1%3A1.6.2.cvs20080610-2
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 14,848 kB
  • ctags: 55,619
  • sloc: ansic: 92,267; asm: 6,692; sh: 4,131; makefile: 2,481; python: 976; pascal: 426; perl: 116
file content (128 lines) | stat: -rw-r--r-- 3,099 bytes parent folder | download | duplicates (2)
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
/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * Joerg Wunsch wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.        Joerg Wunsch
 * ----------------------------------------------------------------------------
 *
 * Demo combining C and assembly source files.
 *
 * $Id: isrs.S,v 1.1 2006/08/29 19:45:06 joerg_wunsch Exp $
 */
/*
 * This file contains the interrupt service routine implementations
 * when compiling the project for the ATtiny13 target.
 */

#include <avr/io.h>

#include "project.h"

#if defined(__AVR_ATtiny13__)

/*
 * Timer 0 hit TOP (0xff), i.e. it turns from up-counting
 * into down-counting direction.
 */
.global TIM0_COMPA_vect
TIM0_COMPA_vect:
	in	sreg_save, _SFR_IO_ADDR(SREG)
	inc	counter_hi
	clr	flags
	out	_SFR_IO_ADDR(SREG), sreg_save
	reti

/*
 * Timer 0 hit BOTTOM (0x00), i.e. it turns from down-counting
 * into up-counting direction.
 */
.global	TIM0_OVF_vect
TIM0_OVF_vect:
	in	sreg_save, _SFR_IO_ADDR(SREG)
	inc	counter_hi
	ser	flags
	out	_SFR_IO_ADDR(SREG), sreg_save
	reti

;;; one 16-bit word to store our rising edge's timestamp
.lcomm	starttime.0, 2

.extern	pwm_incoming
.extern	intbits

.global PCINT0_vect
PCINT0_vect:
	in	sreg_save, _SFR_IO_ADDR(SREG)

	;; save our working registers
	push	r18
	push	r19
	push	r20
	push	r21

	;; Now that we are ready to fetch the current
	;; value of TCNT0, allow interrupts for a
	;; moment.  As the effect of the SEI will be
	;; deferred by one instruction, any possible
	;; rollover of TCNT0 (hitting BOTTOM when
	;; counting down, or MAX when counting up) will
	;; allow the above ISRs to trigger right here,
	;; and update their status, so our combined
	;; 16-bit time from [counter_hi, TCNT0] will
	;; be correct.
	sei
	in	r20, _SFR_IO_ADDR(TCNT0)
	cli
	;; Now, make our working copy of the status,
	;; so we can re-enable interrupts again.
	mov	r21, counter_hi
	mov	r19, flags
	sei

	;; what direction were we counting?
	sbrs	r19, 0
	;; we are down-counting, invert TCNT0
	com	r20
	;; at this point, r21:20 has our current
	;; 16-bit time

	;; now, look which of the edges triggered
	;; our pin-change interrupt
	sbis	_SFR_IO_ADDR(PINB), 4
	rjmp	10f
	;; rising edge detected, just record starttime
	sts	(starttime.0) + 1, r21
	sts	starttime.0, r20
	rjmp	99f		; we are done here

	;; Falling edge: compute pulse width, store it
	;; into pwm_incoming, disable pin-change
	;; interrupt until the upper layers had a chance
	;; to fetch the result.

10:	in	r18, _SFR_IO_ADDR(GIMSK)
	andi	r18, ~(1 << PCIE)
	out	_SFR_IO_ADDR(GIMSK), r18

	;; pwm_incoming = current_time - starttime
	lds	r19, (starttime.0) + 1
	lds	r18, starttime.0
	sub	r20, r18
	sbc	r21, r19
	sts	(pwm_incoming) + 1, r21
	sts	pwm_incoming, r20

	;; signal upper layer
	lds	r18, intbits
	ori	r18, 1
	sts	intbits, r18
99:
	pop	r21
	pop	r20
	pop	r19
	pop	r18

	out	_SFR_IO_ADDR(SREG), sreg_save
	reti
#endif  /* ATtiny13 */