DTMF01.asm


1
/*
2
DTMF-Kanalumschalter für ATV-Relais für Falko Troll, DG2TF
3
Das Programm wertet die Signale eines DTMF-Receivers MT8870 aus und steuert 
4
8 Relais für Auswahl der Audio- und Video-Quelle.
5
6
Zur Steuerung ist ein 4-stelliger DTMF-Code vereinbart, wovon die ersten
7
3 Ziffern fest vereinbart sind (nur durch Neuprogrammierung änderbar) und
8
die vierte Ziffer zur Auswahl des Kanals dient.
9
10
11
(c) 11/2007 hannes.lux@gmx.de
12
13
Das Programm ist für den Tiny2313 (ATMEL-AVR) bestimmt, der mit 1MHz
14
internem Takt läuft. 
15
16
17
Es gilt folgende I/O-Belegung:
18
Port B: H-aktive Ausgänge für die Relais (alle 8 Bits werden benutzt)
19
Port D: Eingänge vom DTMF-Decoder
20
        PD6: Q1
21
        PD5: Q2
22
        PD4: Q3
23
        PD3: Q4
24
        PD2: StD (Strobe)
25
        Die anderen Bits von Port D werden nicht benutzt
26
Port A: unbenutzt
27
28
Alle Eingänge (auch die unbenutzten Portpins) werden durch interne 
29
PullUp-Widerstände auf H-Pegel gezogen um Floaten der Eingänge zu vermeiden.
30
31
Programmbeschreibung:
32
Im Zeitabstand von 10ms werden die Eingänge eingelesen und durch einen
33
hochwirksamen Entprellalgorithmus entprellt. Bei steigender Flanke am
34
StD-Pin wird das Datenwort (die vom MT8870 decodierte Ziffer) übernommen.
35
Dabei werden alle bereits empfangenen Ziffern um eine Position nach links
36
verschoben, so dass immer die zuletzt empfangenen 4 Ziffern verfügbar sind.
37
Wird innerhalb der vereinbarten Ziffern-Lifetime keine neue Ziffer empfangen,
38
so werden alle bereits empfangenen Ziffern gelöscht.
39
Nach jedem Empfang werden die ältesten drei Ziffern mit den vereinbarten
40
Codes (siehe "Vereinbarungen") verglichen und bei Gleichheit wird die
41
letzte Ziffer als Index auf die Tabelle "bimu" benutzt und das entsprechende
42
Bitmuster (das den Schalt-Zustand der Relais repräsentiert) an die Relais
43
ausgegeben. Dabei werden alle bereits empfangenen Ziffern gelöscht, denn
44
das (gültige) Kommando wurde ja ausgeführt.
45
46
Die Code-Zahlen können durch Ändern der Konstanten "zahl1", "zahl2" und
47
"zahl2" umdefiniert werden, die Gültigkeitsdauer der Ziffern mit der
48
Konstante "timeout".
49
50
*/
51
52
.include "tn2313def.inc"    ;Portnamen einbinden
53
54
;Vereinbarungen (dürfen individuell angepasst werden):
55
.equ zahl1=3                ;erste Zahl des DTMF-Codes
56
.equ zahl2=2                ;zweite Zahl des DTMF-Codes
57
.equ zahl3=5                ;dritte Zahl des DTMF-Codes
58
;die vierte Zahl bestimmt als Index das Bitmuster am Relaisport
59
60
.equ timeout=5              ;Timeout Ziffer-Gültigkeit in Sekunden
61
62
;Anschlüsse:
63
.equ relport=portb          ;Relais-Port
64
.equ relddr=ddrb            ;Relais-Datenrichtung
65
.equ dtmfport=portd         ;DTMF-Pull-Up
66
.equ dtmfddr=ddrd           ;DTMF-Datenrichtung
67
.equ dtmfpin=pind           ;DTMF-Eingang
68
.equ bit0=PD6               ;Bit0, Q1
69
.equ bit1=PD5               ;Bit1, Q2
70
.equ bit2=PD4               ;Bit2, Q3
71
.equ bit3=PD3               ;Bit3, Q4
72
.equ bit4=PD2               ;Bit4, StD, Strobe
73
74
;Ende Vereinbarungen
75
76
77
;Registerbelegung.
78
.def null=r2                ;immer Null
79
.def srsk=r3                ;SREG-Siko
80
.def tz0=r4                 ;Tasten-Prellzähler Bit0
81
.def tz1=r5                 ;Tasten-Prellzähler Bit1
82
.def tas=r6                 ;Tastenstatus (gültig)
83
.def zif1=r7                ;Ziffer 1 (älteste, zuerst eingegebene)
84
.def zif2=r8                ;Ziffer 2
85
.def zif3=r9                ;Ziffer 3
86
.def zif4=r10               ;Ziffer 4 (neueste, zuletzt eingegebene)
87
88
.def tmp=r16                ;Kurzzeit-Temp, ungesichert (LCD)
89
.def tfl=r17                ;Tasten-Flags (melden Tastendruck)
90
.def zvt=r18                ;Zeitvorteiler von 10ms auf 1s
91
.def tout=r19               ;Timeout für bereits eingegebene Ziffern
92
93
.def flags=r23              ;einige Steuerflags
94
    .equ entprell=7             ;Flag für Entprellung der Tasten
95
    .equ neusek=6               ;Flag für neue Sekunde
96
97
.def wl=r24                 ;Working L
98
.def wh=r25                 ;Working H
99
100
101
102
103
.cseg               ;Programmspeicher
104
.org 0              ;ab Adresse 0
105
 rjmp RESET         ;Reset Handler
106
 rjmp nix;exint0        ;External Interrupt0 Handler
107
 rjmp nix;INT1          ;External Interrupt1 Handler
108
 rjmp nix;TIM1_CAPT     ;Timer1 Capture Handler
109
 rjmp TIM1_COMPA    ;Timer1 CompareA Handler
110
 rjmp nix;TIM1_OVF      ;Timer1 Overflow Handler
111
 rjmp nix;TIM0_OVF      ;Timer0 Overflow Handler
112
 rjmp nix;USART0_RXC    ;USART0 RX Complete Handler
113
 rjmp nix;USART0_DRE    ;USART0,UDR Empty Handler
114
 rjmp nix;USART0_TXC    ;USART0 TX Complete Handler
115
 rjmp nix;ANA_COMP      ;Analog Comparator Handler
116
 rjmp nix;PCINT         ;Pin Change Interrupt
117
 rjmp nix;TIMER1_COMPB  ;Timer1 Compare B Handler
118
 rjmp nix;TIMER0_COMPA  ;Timer0 Compare A Handler
119
 rjmp nix;TIMER0_COMPB  ;Timer0 Compare B Handler
120
 rjmp nix;USI_START     ;USI Start Handler
121
 rjmp nix;USI_OVERFLOW  ;USI Overflow Handler
122
 rjmp nix;EE_READY      ;EEPROM Ready Handler
123
 rjmp nix;WDT_OVERFLOW  ;Watchdog Overflow Handler
124
nix:                    ;unerlaubte Interrupts
125
 rjmp nix                   ;Falle...
126
127
reset:              ;Programmstart
128
 ldi wl,low(ramend)         ;Stackpointer initialisieren
129
 out SPL,wl
130
 clr null                   ;immer Null
131
 clr tas                    ;Startbedingungen für Entprellung
132
 clr tfl
133
 clr tz0
134
 clr tz1
135
 clr flags
136
 ldi wl,1<<se               ;Sleep-Mode Idle 
137
 out mcucr,wl               ;aktivieren 
138
139
 ldi wl,0                   ;nur Relais 1
140
 rcall schalt               ;einschalten
141
 ldi wl,255                 ;und Port 
142
 out relddr,wl              ;als Ausgang
143
144
 out ddra,null              ;alle unbenutzten und 
145
 out dtmfddr,null           ;DTMF-Ports als Eingang
146
 ldi wl,255                 ;und
147
 out porta,wl               ;Pull-Up-Widerstände
148
 out dtmfport,wl            ;aller Eingänge einschalten
149
150
 ldi wl,low(10000)          ;Timer1-
151
 ldi wh,high(10000)         ;Compare-A-Interrupt
152
 out ocr1ah,wh              ;alle 10000 Takte
153
 out ocr1al,wl              ;(10ms / 100Hz),
154
 out tccr1a,null            ;keine Sonderfunktionen,
155
 out tccr1c,null            ;keine weiteren Sonderfunktionen
156
 ldi wl,(1<<wgm12)+1        ;CTC-Mode und Vorteiler 1:1
157
 out tccr1b,wl              ;einschalten
158
 ldi wl,1<<ocie1a           ;CompareA-Interrupt 
159
 out timsk,wl               ;freischalten
160
 sei                        ;Interrupts global freischalten
161
162
mainloop:           ;Hauptschleife des Programms
163
 sbrc flags,entprell        ;Entprellung erforderlich? - nein...
164
 rcall Tastenabfrage        ;ja...
165
 sbrc flags,neusek          ;eine Sekunde vergangen? - nein...
166
 rcall neusekunde           ;ja...
167
 sleep                      ;CPU-Takt abschalten (Wecken durch Interrupt)
168
 rjmp mainloop              ;nochmal...
169
170
171
Tastenabfrage:  ;liest das decodierte DTMF-Signal ein und entprellt es
172
 ;wird alle 10ms aufgerufen
173
 cbr flags,1<<entprell ;Jobflag löschen
174
 in wl,dtmfpin      ;DTMF_Port einlesen
175
 andi wl,0b01111100 ;nur die relevanten Bits berücksichtigen
176
 clr tmp            ;erstmal alle Bits aus, dann verwirrte Bits entwirren
177
 bst wl,bit0        ;Bit 0
178
 bld tmp,0          ;kopieren
179
 bst wl,bit1        ;Bit 1
180
 bld tmp,1          ;kopieren
181
 bst wl,bit2        ;Bit 2
182
 bld tmp,2          ;kopieren
183
 bst wl,bit3        ;Bit 3
184
 bld tmp,3          ;kopieren
185
 bst wl,bit4        ;Bit 4 (Strobe, StD)
186
 bld tmp,4          ;kopieren
187
 ;nun sind alle Bits am richtigen Platz, 
188
 ;jetzt folgt die eigentliche Entprellung
189
 ;Entprell-Algorithmus nach Peter Dannegger...
190
 eor tmp,tas        ;nur Änderungen gegenüber vorher werden H
191
 and tz0,tmp        ;Prellzähler unveränderter Tasten löschen (Bit0)
192
 and tz1,tmp        ;Prellzähler unveränderter Tasten löschen (Bit1)
193
 com tz0            ;L-Bit zählen 0,2,->1, 1,3,->0
194
 eor tz1,tz0        ;H-Bit zählen 0,2,->tz1 toggeln
195
 and tmp,tz0        ;Änderungen nur dann erhalten, wenn im Prellzähler
196
 and tmp,tz1        ;beide Bits gesetzt sind (Zählerstand 3)
197
 eor tas,tmp        ;erhaltene Änderungen toggeln alten (gültigen) Tastenstatus
198
 and tmp,tas        ;nur (neu) gedrückte Tastenbits bleiben erhalten
199
 or tfl,tmp         ;und zugehörige Bits setzen (gelöscht wird nach Abarbeitung)
200
 ;Entprellung fertig, in "tas" steht jetzt der gültige Tastenzustand,
201
 ;in "tfl" die Flags der neu gedrückten, noch nicht abgearbeiteten Tasten...
202
 sbrs tfl,4         ;Strobe-Bit gesetzt (neues DTMF-Signal)? - ja...
203
 rjmp tasten_end    ;nein, nicht auswerten...
204
205
 ;Es ist ein neues DTMF-Signal eingetroffen
206
 cbr tfl,1<<4               ;Tastenflag löschen
207
 ldi tout,timeout           ;Timeout (Lifetime) der Ziffer setzen
208
 mov zif1,zif2              ;alle Ziffern um eine
209
 mov zif2,zif3              ;Position nach
210
 mov zif3,zif4              ;links schieben,
211
 mov zif4,tas               ;neue Ziffer holen
212
 ldi wl,15                  ;Maske auf Datenbits
213
 and zif4,wl                ;nur die Datenbits stehen lassen
214
215
 ldi wl,zahl1               ;Referenz auf erste Zahl holen und
216
 cp zif1,wl                 ;vergleichen, ist die Ziffer richtig?
217
 brne tasten_end            ;nein, Abbruch...
218
219
 ldi wl,zahl2               ;Referenz auf zweite Zahl holen und
220
 cp zif2,wl                 ;vergleichen, ist die Ziffer richtig?
221
 brne tasten_end            ;nein, Abbruch...
222
223
 ldi wl,zahl3               ;Referenz auf dritte Zahl holen und
224
 cp zif3,wl                 ;vergleichen, ist die Ziffer richtig?
225
 brne tasten_end            ;nein, Abbruch...
226
 ;nun sind die ersten drei Ziffern schonmal richtig
227
228
 mov wl,zif4                ;Ziffer 4 (erlaubter Wert 1 bis 8) kopieren
229
 dec wl                     ;um 1 vermindern um sie als Index (0 bis 7)
230
                            ;nutzen zu können
231
 cpi wl,8                   ;Wert im erlaubten Bereich (unter 8)?
232
 brcc tasten_end            ;nein, Abbruch...
233
234
schalt:
235
 ldi zl,low(bimu*2)         ;Z-Pointer auf
236
 ldi zh,high(bimu*2)        ;Tabelle mit Bitmustern
237
 add zl,wl                  ;Index dazu addieren
238
 adc zh,null                ;Übertrag auch
239
 lpm                        ;Bitmuster nach r0 holen
240
 out relport,r0             ;und an Relaisport ausgeben
241
 clr zif1                   ;alle 
242
 clr zif2                   ;empfangenen
243
 clr zif3                   ;Ziffern
244
 clr zif4                   ;löschen
245
 clr tout                   ;Timeout deaktivieren
246
tasten_end:
247
 ret                ;fertig und zurück...
248
249
250
251
neusekunde:             ;UP, eine Sekunde ist vergangen
252
 cbr flags,1<<neusek        ;Jobflag löschen
253
 tst tout                   ;ist der Timeout überhaupt aktiv?
254
 breq neusek_end            ;nein, wenn 0, nichts tun...
255
 dec tout                   ;ja, runterzählen
256
 brne neusek_end            ;unten? - nein, wenn nicht 0, nichts tun...
257
 ;Timeout (Lifetime DTMF-Ziffer) ist abgelaufen
258
 clr zif1                   ;alle 
259
 clr zif2                   ;empfangenen
260
 clr zif3                   ;Ziffern
261
 clr zif4                   ;löschen
262
neusek_end:
263
 ret                        ;fertig und zurück
264
265
266
267
TIM1_COMPA:         ;ISR, Timer1-Compare A (alle 10ms)
268
 in srsk,sreg               ;SREG sichern
269
 sbr flags,1<<entprell      ;Entprellung anmelden
270
 inc zvt                    ;Zeitvorteiler (Hundertstelsekunde) hoch
271
 cpi zvt,100                ;Sekunde erreicht oder überschritten?
272
 brcs tim1_1                ;nein...
273
 clr zvt                    ;ja, von vorn beginnen
274
 sbr flags,neusek           ;neue Sekunde anmelden
275
tim1_1:
276
 out sreg,srsk              ;SREG wiederherstellen
277
 reti                       ;fertig...
278
279
280
bimu:               ;Bitmuster für Relaisport
281
.db 0b00000001,0b00000010   ;1,2
282
.db 0b00000100,0b00001000   ;3,4
283
.db 0b00010000,0b00100000   ;5,6
284
.db 0b01000000,0b10000000   ;7,8