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