ServoTester_ATTiny13.asm


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