1 | ;************************************************************************************
|
2 | ; register definitions for ATTiny13
|
3 | ;************************************************************************************
|
4 | .include "tn13def.inc"
|
5 |
|
6 | ;************************************************************************************
|
7 | ; local register definitions
|
8 | ;************************************************************************************
|
9 | .def ADC_REF_L = R0 ; reference adc (=mid position) value low
|
10 | .def ADC_REF_H = R1 ; reference adc (=mid position) value high
|
11 | .def SREG_BACK0 = R2 ; SREG backup during interrupt
|
12 |
|
13 |
|
14 |
|
15 | .def WORK0 = R16 ; temporary register
|
16 | .def WORK1 = R17 ; temporary register
|
17 | .def PARAM0 = R18 ; parameter register
|
18 |
|
19 | .def ADC_L = R20 ; adc result low
|
20 | .def ADC_H = R21 ; adc result high
|
21 | .def TIMER_UPPER = R22 ; upper timer 0 value
|
22 |
|
23 | ;************************************************************************************
|
24 | ; port definitions
|
25 | ;************************************************************************************
|
26 | .set PUSHBUTTON = 0 ; input for reference pushbutton
|
27 | .set POTENTIOMETER = 2 ; analog control input
|
28 | .set RC_OUT = 4 ; RC pulse output
|
29 |
|
30 |
|
31 | ;************************************************************************************
|
32 | ; Resetvector
|
33 | ;************************************************************************************
|
34 | .cseg
|
35 |
|
36 | .org 0x0000 ; Reset vector
|
37 | rjmp reset_entry ; reset entry
|
38 |
|
39 | ;************************************************************************************
|
40 | ; Interruptvectors
|
41 | ;************************************************************************************
|
42 |
|
43 | .org 0x0001 ; External Interrupt Request 0
|
44 | reti ; not handled
|
45 |
|
46 | .org 0x0002 ; Pin Change Interrupt Request 0
|
47 | reti ; not handled
|
48 |
|
49 | .org 0x0003 ; Timer/Counter0 Overflow
|
50 | reti ; not handled
|
51 |
|
52 | .org 0x0004 ; EEPROM ready
|
53 | reti ; not handled
|
54 |
|
55 | .org 0x0005 ; Analog comparator
|
56 | reti ; not handled
|
57 |
|
58 | .org 0x0006 ; Timer0 Compare Match A
|
59 | in SREG_BACK0,SREG ; save SREG
|
60 | inc TIMER_UPPER ; increment upper timer value
|
61 | out SREG,SREG_BACK0 ; restore SREG
|
62 | reti ; over and out
|
63 |
|
64 | ;.org 0x0007 ; Timer0 Compare Match B
|
65 | ;reti ; not handled
|
66 |
|
67 | ;.org 0x0008 ; Watchdog Timeout
|
68 | ;reti ; not handled
|
69 |
|
70 | ;.org 0x0009 ; ADC conversion complete
|
71 | ;reti ; not handled
|
72 |
|
73 |
|
74 |
|
75 | ;************************************************************************************
|
76 | ; Reset entry
|
77 | ;************************************************************************************
|
78 | reset_entry:
|
79 | ; prepare port b
|
80 | sbi PORTB,PUSHBUTTON ; enable internal pullups for Pushbutton
|
81 | ldi WORK0,(1<<RC_OUT) ; RC pin as output
|
82 | out DDRB,WORK0 ; setup port b direction
|
83 | ; setup ADC
|
84 | ldi WORK0,(1<<ADC1D) ; Disable ADC pin as digital input
|
85 | out DIDR0,WORK0 ; set
|
86 | ldi WORK0,1<<MUX0 ; ADC1
|
87 | out ADMUX,WORK0 ; Setup multiplexer
|
88 | ; Enable ACD / Prescaler 128 (62,5kHz -> samling frq >= 2500Hz)
|
89 | ldi WORK0,(1<<ADEN)+(1<<ADPS2)+(1<<ADPS1)+(1<<ADPS0)
|
90 | out ADCSRA,WORK0 ; prepare ADC
|
91 |
|
92 | ; Wait for 0.5s to start up
|
93 | ldi PARAM0,50 ; 50*10ms
|
94 | rcall wait_n10ms ; do wait
|
95 |
|
96 | ; Get inital state of the adc (reference position)
|
97 | rcall adc_conv ; get adc
|
98 | movw ADC_REF_H:ADC_REF_L,\
|
99 | ADC_H:ADC_L ; store reference position
|
100 |
|
101 | ; setup Timer0
|
102 | ldi TIMER_UPPER,0 ; init upper timer value
|
103 | ldi WORK0,(1<<WGM01) ; mode: clear on compare match
|
104 | out TCCR0A,WORK0 ; set mode of operation
|
105 | ldi WORK0,150-1 ; compare match every 125µs @9.6Mhz
|
106 | out OCR0A,WORK0 ; set compare match value
|
107 | ldi WORK0,(1<<OCIE0A) ; Timer0 compare match interrupt
|
108 | out TIMSK0,WORK0 ; Enable interrupt
|
109 | sei ; global enable
|
110 | ldi WORK0,(1<<CS01) ; Clk/8 -> 1.2Mhz
|
111 | out TCCR0B,WORK0 ; Start Timer0 with 1.2Mhz
|
112 |
|
113 | main_loop:
|
114 | ; in the first millisecond get next adc and button
|
115 | sbi PORTB,RC_OUT ; set RC out
|
116 | rcall adc_conv ; get adc
|
117 | sbis PINB,PUSHBUTTON ; check if button is pressed
|
118 | movw ADC_REF_H:ADC_REF_L, \
|
119 | ADC_H:ADC_L ; if button pressed store reference position
|
120 | ; calculate pulse width
|
121 | sub ADC_L,ADC_REF_L ; calc difference low
|
122 | sbc ADC_H,ADC_REF_H ; calc difference high
|
123 | ; ldi WORK0,1 ; shift loop count
|
124 | ;zz_shift:
|
125 | ; asr ADC_H
|
126 | ; ror ADC_L
|
127 | ; dec WORK0
|
128 | ; brne zz_shift
|
129 | ; inc ADC_H
|
130 |
|
131 | ldi WORK0,68 ; set offset low
|
132 | add ADC_L,WORK0 ; add offset low
|
133 | ldi WORK0,9 ; set offset high
|
134 | adc ADC_H,WORK0 ; add offset high
|
135 |
|
136 | zz_wait_075ms:
|
137 | cpi TIMER_UPPER,6 ; 6*125µs = 0.75ms
|
138 | brne zz_wait_075ms ; wait for first 0.75ms to finish
|
139 | ; wait for pulse to finish
|
140 | zz_finish_loop:
|
141 | subi ADC_L,1
|
142 | brcc zz_finish_loop
|
143 | subi ADC_H,1
|
144 | brpl zz_finish_loop
|
145 |
|
146 | cbi PORTB,RC_OUT ; reset RC out
|
147 |
|
148 | zz_wait_20ms:
|
149 | cpi TIMER_UPPER,160 ; 160*125µs = 20ms
|
150 | brne zz_wait_20ms ; wait for first 20ms to finish
|
151 | ldi TIMER_UPPER,0 ; reset upper counter
|
152 |
|
153 | rjmp main_loop ; continue with next loop
|
154 |
|
155 |
|
156 |
|
157 | ;------------------------------------------------------------------------------------
|
158 | ; wait_n10ms: Waits for PARAM0*10ms
|
159 | ; Registers changed: PARAM0,WORK1,WORK0
|
160 | ;------------------------------------------------------------------------------------
|
161 | wait_n10ms:
|
162 | ldi WORK0,200 ; Loop 2
|
163 | zz_wait_loop2:
|
164 | ldi WORK1,159 ; Loop 1
|
165 | zz_wait_loop1:
|
166 | dec WORK1 ; decrement loop count 1
|
167 | brne zz_wait_loop1 ; repeat loop 1
|
168 | dec WORK0 ; decrement loop count 2
|
169 | brne zz_wait_loop2 ; repeat loop 2
|
170 | dec PARAM0 ; decrement parameter loop count
|
171 | brne wait_n10ms ; repeat parameter loop
|
172 | ret
|
173 |
|
174 |
|
175 | ;------------------------------------------------------------------------------------
|
176 | ; adc_conv: Multiple conversion of adc.
|
177 | ; The result is found in ADC_H:ADC_L
|
178 | ; WORK0 is changed.
|
179 | ;------------------------------------------------------------------------------------
|
180 | adc_conv:
|
181 | ; setup adc sum & loop count
|
182 | ldi WORK1,4 ; setup adc loop
|
183 | ldi ADC_L,0 ; init adc sum low
|
184 | ldi ADC_H,0 ; init adc sum high
|
185 | zz_adc_loop:
|
186 | sbi ADCSRA,ADSC ; start conversion
|
187 | zz_adc_wait:
|
188 | sbic ADCSRA,ADSC ; check for adc to complete
|
189 | rjmp zz_adc_wait ; not yet finshed wait more
|
190 | in WORK0,ADCL ; get adc result low
|
191 | add ADC_L,WORK0 ; add to sum low
|
192 | in WORK0,ADCH ; get adc result high
|
193 | adc ADC_H,WORK0 ; add to sum high
|
194 | dec WORK1 ; decrement loop count
|
195 | brne zz_adc_loop ; one more adc to go
|
196 | ret ; over and out
|