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
|