Pfad: Home => AVR-Übersicht => Anwendungen => PCM-Decoder => Quellcode

Assembler Quellcode für den PCM-Dekoder


; *******************************************************************
; * PCM2PWG-Dekoder fuer AT90S2323, Version 0.4 vom 20.12.2000      *
; * Dekodiert PCM Pulse in pulsweitenmoduliertes Rechtecksignal     *
; * (C)2000 by info!at!avr-asm-tutorial.net                         *
; *******************************************************************
;
; Momentan eingestellt auf PCM-Signale von 800 bis 2200 Ás und 4 MHz
; Taktfrequenz des Prozessors.
; Durch Anpassung der Konstanten unten kann der Code an andere Signale
; angepasst werden.
;
;   VCC  LED  PWG  PCM      PCM-Ein: 25ms = 40 Hz Frequenzeingang
;        Aus  Aus  Ein               positiv gepulste PCM-Signale
;  +-8----7----6----5--+
;  |                   |    PWG-Aus: 1.4 ms = 714 Hz Ausgangsfrequenz
;  O    AT 90 S 2323   |             positiv gepulst fuer 0..1,4 ms
;  |                   |
;  +-1----2----3----4--+    LED-Aus: Ausgang auf Null, wenn Fehler
;   RST  XT1  XT2  GND
;
; ********* Eingangssignal PCM-kodiert ************************
;
; Phase   I     II     III   IV   V       VI   VII
;  PCM  1----         --------------------               ------
;  Ein   \\\\\       /         \\\\\\\\\\\\             /
;       0------------           ------------------------
;
; ********* Ausgangssignal Pulsweite-Oszillator ***************
;
;  PWG  1     -------------               ------
;  Aus       /             \             /
;       0----               -------------
;  Zeit Ás   |<--0..cCycl->|<-cCycl..0-->|   800 - 2200 Ás:
;            |<----------cCycl---------->|   cCycl = 1400 Ás
;
; *************************************************************
;
.NOLIST
.INCLUDE "2323def.inc"
.LIST
;
; Verwendete Register
;
.DEF rmpr = R16  ; Vielzweckregister
.DEF rdel = R17  ; Register fuer Verzoergerungsschleifen
.DEF rpwc = R18 ; Zaehler fuer den Pulsweiten-Generator
.DEF rpws = R19 ; Aktueller Ausgangswert fuer den Pulsweiten-Generator
.DEF rpwn = R20 ; Naechster Wert fuer Pulsweiten-Generator
.DEF rtry = R21 ; Anzahl der zulaessigen Fehlversuche
.DEF rctr = R22 ; Zaehler fuer aktive Schleifen
.DEF rerr = R23 ; Anzahl Fehlversuche
; ZL = R30 and ZH = R31 werden fuer lange Zeitschleifen benutzt
;
; IO-Port-Bits
;
.EQU pbmode = 0b00000110 ; Port B Port-Modus
.EQU bIn = 0 ; Eingangspin 0, positive Polaritaet
.EQU bOut = 1 ; Ausgabe fuer Pulsweitengenerator
.EQU bFail = 2 ; Ausgang fuer die Fehler-LED, aktiv Null
;
; Konstanten (1 Zyklus = 6 Ás = 24 Taktzyklen bei 4 MHz)
;
; Anpassung der Quarzfrequenz an andere Taktfrequenzen des Prozessors
;
.EQU cXtal = 4 ; Taktfrequenz in MHz
;
; Anpassung der Gesamtlaenge an andere Eingangssignale
;
.EQU cPulseDuration = 25000 ; Gesamtdauer des Eingangsimpulses in Ás
;
; Anpassung der Zeiten an andere PCM-Pulsweiten
;
.EQU cMinPulse = 800 ; Minimum Pulsdauer in Ás
.EQU cMaxPulse = 2200 ; Maximum Pulsdauer in Ás
;
; Anpassung des Defaultwertes fuer den Pulsweiten-Generator bei
; Fehlsignalen oder Signalverlust, 0%: Ausgang wird Null, 100%:
; Ausgang wird dauerhaft Eins, 50%: Ausgang geht auf 50% Pulsweite
;
.EQU cFallBackValue = 50 ; 50% Pulsweite
;
; Die folgenden Werte werden automatisch aus den obigen Angaben
; ausgerechnet. Bitte nur aendern, wenn Du weisst was Du tust!
;
.EQU cUnitLength = 24 ; Taktzyklen pro Schleifendurchgang
.EQU cCycleLength = cUnitLength/cXtal ; Gesamtschleifendauer in Ás
.EQU cCycl = cPulseDuration/cCycleLength ; Schleifen in 25 ms
.EQU cStep = (cMaxPulse-cMinPulse)/cCycleLength ; Aktive Schleifen
.EQU cTolerance = cStep/10; Tolerierte Frueh- und Spaetschleifendauer
.EQU cMinSteps = cMinPulse/cCycleLength ; Schleifen bis zum Zaehlbeginn
.EQU cMaxSteps = cMaxPulse/cCycleLength ; Schleifen nach Zaehlende
.EQU cMin1 = cMinSteps-cTolerance-1 ; Mindestschleifen mit Eingang hoch
.EQU cTlp = cTolerance-1 ; Fruehzeitige inaktive Schleifen, toleriert
.EQU cTla = cTolerance ; Schleifen nach Ende der aktiven Zaehlzeit
.EQU cMin0 = (cCycl-cMaxSteps)*90/100 ; Schleifen mit inaktivem Signal
.EQU cFbck = 1 ; Number of false signals to tolerate before default is set
.EQU cDflt = cstep*cFallbackValue/100 ; Default-Wert fuer den PWG
;
; Makros fuer den Error-LED-Ausgang (auf Aktiv low eingestellt)
;
.MACRO   LedErrOn
   CBI   PortB,bFail
.ENDM
.MACRO   LedErrOff
   SBI   PortB,bFail
.ENDM
;
; Makros fuer Verzoegerungen
;
.MACRO   Delay1 ; Einzelschritt
   NOP
.ENDM
;
.MACRO   Delay2 ; Doppelschritt
   NOP
   NOP
.ENDM
;
.MACRO   Delay3 ; Verzoegerung um Vielfache von je 3 Schritten
   LDI   rdel,@0
MD3:
   DEC   rdel
   BRNE   MD3
.ENDM
;
.MACRO	Delay4 ; Verzoegerung um Vielfache von je 4 Schritten
   LDI   rdel,@0
MD4:
   DEC   rdel
   NOP
   BRNE  MD4
.ENDM
;
.MACRO   MacPwm ; Makro fuer den Pulsweiten-Generator
   DEC   rpwc      ; 1  1  1  1
   BREQ   MAP2     ; 1  1  2  2
   CP   rpws,rpwc  ; 1  1
   BRCS   MAP1     ; 1  2
   NOP             ; 1
   CBI   PortB,bOut; 2
   RJMP   MAP3     ; 2
MAP1:
   SBI   PortB,bOut;    2
   RJMP   MAP3     ;    2
MAP2:
   MOV   rpws,rpwn ;       1  1
   LDI   rpwc,cstep;       1  1
   SBI   PortB,bOut;       2  2
   NOP             ;       1  1
   NOP             ;       1  1
MAP3:              ;-----------
                   ; 9  9  9  9
                   ;===========
.ENDM
;
; Beginn des Hauptprogrammes, initiere Variablen
;
Start:
   LDI   rpwc,cDflt ; Zaehler fuer den PWG
   LDI   rpws,cDflt ; Aktueller PWG-Wert
   LDI   rpwn,cDflt ; Naechster PWG-Wert

; Initiiere den Port B
;
   LDI   rmpr,pbmode ; Setze Datenrichtungsregister
   OUT   DDRB,rmpr   ; von Port B
   SBI   PortB,bIn ; Schalte Pull-Up-Widerstand am Eingang an

; Starte Phase I : Warte bis der Eingang Null wird
;
; Schalte Fehler ein, bis das Signal korrekt ist
;
PH1:
   MacPwm          ;    9
   LDI   rerr,cFbck;    1
   LDI   rpwn,cDflt;    1
   LedErrOn        ;    2
   Delay3(3)       ;    9
;
; Setze maximale Zeitdauer fuer die Erkennung eines Null-Signals
;
PH1a:
   LDI   ZL,Low(cCycl); 1
   LDI   ZH,HIGH(cCycl);1
;                     ---
;                      24
;                     ===
; Warte bis der Eingang Null ist oder Zeitueberlauf eintritt
;
PH1b:
   MacPwm          ;  9  9  9
   SBIS   PinB,bIn ;  2  2  1
   RJMP   PH2      ;        2
   SBIW   ZL,1     ;  2  2
   BREQ   PH1c     ;  1  2
   Delay4(2)       ;  8
   RJMP   PH1b     ;  2
;                   ---
;                    24
;                   ===
; Zeitueberlauf mit Eingang auf Eins
;
PH1c:              ;   (15)
   Delay4(1)       ;     4
;
; Fehler bei aktivem Eingang, zaehle die Fehler
;
PH1d:              ;(19 19)
   DEC   rerr      ;  1  1
   BRNE   PH1a     ;  2  1
;
; Zu viele Fehler in Folge, setze Fehlerbedingung
;
   Delay1          ;     1
   RJMP   PH1      ;     2
;                      ---
;                       24
;                      ===
; Starte Phase II: Eingang ist Null, warte auf aktives Signal
;
PH2:               ;      (12)
   Delay3(2)       ;        6
   Delay2          ;        2
   RJMP   PH2b     ;        2
;
; Fehler aufgetreten, setze Fehlerbedingung
;
PH2a:
   MacPwm          ;     9
   LDI   rerr,cFbck;     1
   LDI   rpwn,cDflt;     1
   LedErrOn        ;     2
   Delay3(3)       ;     9
;
; Setze Zaehler fuer Zeitueberlauf bei inaktivem Eingang
;
PH2b:              ;   (22 22)
   LDI   ZL,LOW(cCycl);  1  1
   LDI   ZH,HIGH(cCycl); 1  1
;                      ------
;                       24 24
;                      ======
; Warte bis der Eingang eins ist oder Zeitueberlauf passiert
;
PH2c:
   MacPwm          ;  9  9  9  9
   SBIC   PinB,bIn ;  2  2  2  1
   RJMP   PH3      ;           2
   SBIW   ZL,1     ;  2  2  2
   BREQ   PH2d     ;  1  2  2
   Delay4(2)       ;  8
   RJMP   PH2c     ;  2
;                   ---
;                    24
;                   ===
; Zeitueberlauf bei inaktivem Eingang, zaehle Fehler
;
PH2d:              ;   (15 15)
   Delay4(1)       ;     4  4
PH2e:              ;   (19 19)
   DEC   rtry      ;     1  1
   BRNE   PH2b     ;     1  2
   NOP             ;     1
   RJMP   PH2a     ;     2
;                      ---
;                       24
;                      ===
; Phase III: Eingang ist aktiv geworden, warte cMin1 Schleifen, ob stabil
;
PH3:               ;   (12)
   Delay3(3)       ;     9
   Delay2          ;     2
   LDI   rtry,cMin1;     1
;                      ---
;                       24
;                      ===
; Warte bis cMin1 Schleifen mit aktivem Eingang abgelaufen
;
PH3a:
   MacPwm          ;  9  9  9
   SBIS   PinB,bIn ;  2  2  1
   RJMP   PH3b     ;        2
   DEC   rtry      ;  1  1
   BREQ   PH4      ;  1  2
   Delay3(3)       ;  9
   RJMP   PH3a     ;  2
;                   ---
;                    24
;                   ===
; Fruehes Inaktivierung des Einganges, Fehler bei Eingang Null
;
PH3b:              ;       (12)
   Delay3(1)       ;         3
   Delay2          ;         2
   RJMP   PH2e     ;         2
;
; Phase IV: Eingang ist Eins fuer cMin1 Schleifen, starte Toleranzzeit
;
PH4:               ;(14)
   Delay4(2)       ;  8
   LDI   rtry,cTlp ;  1
   LDI   rctr,cstep;  1
;                   ---
;                    24
;                   ===
; Warte fuer Toleranzzeit oder auf inaktiven Eingang
;
PH4a:
   MacPwm          ;  9  9  9
   SBIS   PinB,bIn ;  2  2  1
   RJMP   PH7      ;        2
   DEC   rtry      ;  1  1
   BREQ   PH5      ;  1  2
   Delay3(3)       ;  9
   RJMP   PH4a     ;  2
;                   ---
;                    24
;                   ===
;
; Phase V: Ende der Toleranzzeit, beginne Abwaertszaehlung
;
PH5:               ;   (14)
   Delay4(2)       ;     8
   Delay2          ;     2
;                      ---
;                       24
;                      ===
PH5a:
   MacPwm          ;  9  9  9
   SBIS   PinB,bIn ;  2  2  1
   RJMP   PH7      ;        2
   DEC   rctr      ;  1  1
   BREQ   PH6      ;  1  2
   Delay3(3)       ;  9
   RJMP   PH5a     ;  2
;                   ---
;                    24
;                   ===
; Phase VI: Ende des Abwaertszaehlens, toleriere Nachlaufzeit
;
PH6:               ;   (14)
   Delay3(3)       ;     9
   LDI   rtry,cTla ;     1
;                      ---
;                       24
;                      ===
; Zeitueberlauf nach cTla Schleifen, beende bei Ueberlauf oder inaktiv
;
PH6a:
   MacPwm          ;  9  9  9
   SBIS   PinB,bIn ;  2  2  1
   RJMP   PH7      ;        2
   DEC   rtry      ;  1  1
   BREQ   PH6b     ;  1  2
   Delay3(3)       ;  9
   RJMP   PH6a     ;  2
;                   ---
;                    24
;                   ===
; Aktives Signal zu lang, Fehlerbedingung mit aktivem Eingang
;
PH6b:              ;   (14)
   Delay3(1)       ;     3
   RJMP   PH1d     ;     2
;
; Phase VII: Eingang inaktiv, pruefe auf ausreichende inaktive Zeit
;
;
PH7:               ;   (12)
   Delay4(2)       ;     8
   Delay2          ;     2
   LDI   ZL,LOW(cMin0);  1
   LDI   ZH,HIGH(cMin0); 1
;                      ---
;                       24
;                      ===
PH7a:
   MacPwm          ;  9  9  9
   SBIC   PinB,bIn ;  2  2  1
   RJMP   PH7b     ;        2
   SBIW   ZL,1     ;  2  2
   BREQ   PH7c     ;  1  2
   Delay4(2)       ;  8
   RJMP   PH7a     ;  2
;                   ---
;                    24
;                   ===
; Fruehzeitiges Ende der Signalpause, Fehlerbedingung bei inaktivem Eingang
;
PH7b:              ;      (12)
   Delay3(1)       ;        3
   Delay2          ;        2
   RJMP   PH1d     ;        2
;
; Ende der Mindestdauer des inaktiven Signals, setze neuen Messwert
;
PH7c:              ;   (15)
   MOV   rpwn,rctr ;     1
   LDI   rerr,cFbck;     1
   LedErrOff       ;     2
   Delay1          ;     1
   RJMP   PH2b     ;     2
;
; Ende des Programmes
;


©2002 by http://www.avr-asm-tutorial.net