Path: Home => AVR-Overview => Applications => PCM-Decoder => Source code

; *******************************************************************
; * PCM2PWG-Decoder for AT90S2323, Version 0.4 as of 20.12.2000     *
; * Translates pulse coded input to Pulse Width Generator Output    *
; * (C)2000 by info!at!avr-asm-tutorial.net                         *
; *******************************************************************
;
; Currently adjusted for 800 to 2200 Ás signals and 4 MHz.
; Adjust constants below to fit to other timings!
;
;   VCC  LED  PWG  PCM      PCM-Inp: 25ms = 40 Hz cycle time
;        Out  Out  Inp               active high pulse encoded signal
;  +-8----7----6----5--+
;  |                   |    PWG-Out: 1.4 ms = 714 Hz cycle time
;  O    AT 90 S 2323   |             active high for 0..1.4 ms
;  |                   |
;  +-1----2----3----4--+    LED-Out: Active low if error occurs
;   RST  XT1  XT2  GND
;
; ********* Input Signal PCM encoded **************************
;
; Phase   I     II     III   IV   V       VI   VII
;  PCM  1----         --------------------               ------
;  Inp   \\\\\       /         \\\\\\\\\\\\             /
;       0------------           ------------------------
;
; ********* Output Signal Pulse Width Generator ***************
;
;  PWG  1     -------------               ------
;  Out       /             \             /
;       0----               -------------
;  Time Ás   |<--0..cCycl->|<-cCycl..0-->|   800 - 2200 Ás:
;            |<----------cCycl---------->|   cCycl = 1400 Ás
;
; *************************************************************
;
.NOLIST
.INCLUDE "2323def.inc"
.LIST
;
; Used registers
;
.DEF rmpr = R16  ; Multi Purpose register
.DEF rdel = R17  ; Register for delay loops
.DEF rpwc = R18 ; Counter for pulse width generator
.DEF rpws = R19 ; Current setting of pulse width generator
.DEF rpwn = R20 ; Next setting of the pulse width generator
.DEF rtry = R21 ; Number of retries
.DEF rctr = R22 ; Counter for active cycles
.DEF rerr = R23 ; Number of failures
; ZL = R30 and ZH = R31 used for counting long times
;
; IO-Port-Bits
;
.EQU pbmode = 0b00000110 ; Port B Output pins
.EQU bIn = 0 ; Input pin is 0, active high
.EQU bOut = 1 ; Output pin for PWG, pulse width generator
.EQU bFail = 2 ; Output pin for failure LED, active low
;
; Constants (1 cycle = 6 Ás = 24 clock cycles @ 4 MHz)
;
; Adjust the xtal frequency for other clocks
;
.EQU cXtal = 4 ; Crystal frequency in MHz
;
; Adjust this cycle length for other total lengthes of the input signal
;
.EQU cPulseDuration = 25000 ; Total pulse length in Ás
;
; Adjust the timing for other active high encoder pulses
;
.EQU cMinPulse = 800 ; Minimum pulse length in Ás
.EQU cMaxPulse = 2200 ; Maximum pulse length in Ás
;
; Adjust this fallback value in % of total duration if errors or
; signal-losses occur, 0%: Output is low, 100%: output is high,
; 50%: Output is 50% pulse width
;
.EQU cFallBackValue = 50 ; 50% pulse width
;
; The following are automatically calculated from the above,
; don't adjust these without knowing what you do!
;
.EQU cUnitLength = 24 ; Clock cycles per unit loop
.EQU cCycleLength = cUnitLength/cXtal ; Total cycle length in Ás
.EQU cCycl = cPulseDuration/cCycleLength ; Cycles in 25 ms
.EQU cStep = (cMaxPulse-cMinPulse)/cCycleLength ; Active cycles
.EQU cTolerance = cStep/10; Tolerated short/long signal length
.EQU cMinSteps = cMinPulse/cCycleLength ; Start counting active pulse
.EQU cMaxSteps = cMaxPulse/cCycleLength ; Stop counting active pulse
.EQU cMin1 = cMinSteps-cTolerance-1 ; Unit loops that must be active high
.EQU cTlp = cTolerance-1 ; Early low units that are tolerated as Zero
.EQU cTla = cTolerance ; Late units tolerated as One
.EQU cMin0 = (cCycl-cMaxSteps)*90/100 ; Units that must be inactive
.EQU cFbck = 1 ; Number of false signals to tolerate before default is set
.EQU cDflt = cstep*cFallbackValue/100 ; Default fallback value for PWG
;
; Macros for Error-LED-Out (Active low)
;
.MACRO   LedErrOn
   CBI   PortB,bFail
.ENDM
.MACRO   LedErrOff
   SBI   PortB,bFail
.ENDM
;
; Macros for delays
;
.MACRO   Delay1 ; Single delay step
   NOP
.ENDM
;
.MACRO   Delay2 ; Double delay step
   NOP
   NOP
.ENDM
;
.MACRO   Delay3 ; Delay macro for multiples of 3 steps
   LDI   rdel,@0
MD3:
   DEC   rdel
   BRNE   MD3
.ENDM
;
.MACRO	Delay4 ; Delay Macro for multiples of 4 steps
   LDI   rdel,@0
MD4:
   DEC   rdel
   NOP
   BRNE  MD4
.ENDM
;
.MACRO   MacPwm ; Macro for Pulse Width 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
;
; Start of main program, Init variables
;
Start:
   LDI   rpwc,cDflt ; Counter of the pwm
   LDI   rpws,cDflt ; Current pwm value
   LDI   rpwn,cDflt ; Next pwg value
;
; Init the Port B
;
   LDI   rmpr,pbmode ; Set data direction mode
   OUT   DDRB,rmpr   ; on Port B
   SBI   PortB,bIn ; Switch pull-up resistor on
;
; Start phase I : Wait until input is pulled low
;
; Set error condition until signal is correct
;
PH1:
   MacPwm          ;    9
   LDI   rerr,cFbck;    1
   LDI   rpwn,cDflt;    1
   LedErrOn        ;    2
   Delay3(3)       ;    9
;
; Set one cycle length for negative edge detection
;
PH1a:
   LDI   ZL,Low(cCycl); 1
   LDI   ZH,HIGH(cCycl);1
;                     ---
;                      24
;                     ===
; Wait until input is pulled low or timeout occurs
;
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
;                   ===
; Timed out with input high
;
PH1c:              ;   (15)
   Delay4(1)       ;     4
;
; Error occured with input high, count subsequent errors
;
PH1d:              ;(19 19)
   DEC   rerr      ;  1  1
   BRNE   PH1a     ;  2  1
;
; Too many subsequent errors with input high, set error condition
;
   Delay1          ;     1
   RJMP   PH1      ;     2
;                      ---
;                       24
;                      ===
; Start Phase II: Input is low, wait for pulse or timeout
;
PH2:               ;      (12)
   Delay3(2)       ;        6
   Delay2          ;        2
   RJMP   PH2b     ;        2
;
; Error occured with input low, set error condition
;
PH2a:
   MacPwm          ;     9
   LDI   rerr,cFbck;     1
   LDI   rpwn,cDflt;     1
   LedErrOn        ;     2
   Delay3(3)       ;     9
;
; Set counter for time out during input low
;
PH2b:              ;   (22 22)
   LDI   ZL,LOW(cCycl);  1  1
   LDI   ZH,HIGH(cCycl); 1  1
;                      ------
;                       24 24
;                      ======
; Wait until input goes high or time-out occurs
;
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
;                   ===
; Time out during input low, count subsequent errors
;
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: Input gone high, check for cMin1 phases if stable
;
PH3:               ;   (12)
   Delay3(3)       ;     9
   Delay2          ;     2
   LDI   rtry,cMin1;     1
;                      ---
;                       24
;                      ===
; Wait until cMin1 phases passed with input high
;
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
;                   ===
; Early low detected during cMin1-phase, error with input low
;
PH3b:              ;       (12)
   Delay3(1)       ;         3
   Delay2          ;         2
   RJMP   PH2e     ;         2
;
; Phase IV: Input is high for cMin1, pre-tolerance time
;
PH4:               ;(14)
   Delay4(2)       ;  8
   LDI   rtry,cTlp ;  1
   LDI   rctr,cstep;  1
;                   ---
;                    24
;                   ===
; Wait for pre-tolerance time or input early low
;
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: End of pre-tolerance has been reached, count down now
;
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: End of count reached, tolerate overtime
;
PH6:               ;   (14)
   Delay3(3)       ;     9
   LDI   rtry,cTla ;     1
;                      ---
;                       24
;                      ===
; Overtime for cTla, break if overtime or input low
;
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
;                   ===
; Active signal too long, failure condition with input high
;
PH6b:              ;   (14)
   Delay3(1)       ;     3
   RJMP   PH1d     ;     2
;
; Phase VII: Input inactive, check minimum inactive time
;
;
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
;                   ===
; Early end of minimum inactive time, failure condition with input high
;
PH7b:              ;      (12)
   Delay3(1)       ;        3
   Delay2          ;        2
   RJMP   PH1d     ;        2
;
; End of minimum inactive time reached, set result, restart with input low
;
PH7c:              ;   (15)
   MOV   rpwn,rctr ;     1
   LDI   rerr,cFbck;     1
   LedErrOff       ;     2
   Delay1          ;     1
   RJMP   PH2b     ;     2
;
; End of the program
;



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