TITL 'Timer Subroutines' *----------------------------------------------------------- * * Timer Subroutines TONS, TOFFS, and TONOFS * *----------------------------------------------------------- * * Erland Muller * 08.05.02 * * These subroutines are ment to be called from within * the corresponding macros TON, TOFF, and TONOFF only. * Please read "controlmacro_0x.asm" and "controlmacro.html". * * The subroutines are called with: * * RVKE = ROL (Current Result of Logical Operation) * ;RDREF-1 = address of the structure{ * bool QS, bool VKES, * unsigned CurrTime, unsigned MultiplCount} * RLINK = address of the parameter structure{ * unsigned TimeLimit, MultiplierConstant} * @SLCNT = unsigned CurrentTime running from 0 or 1 * to MAXCNT * MAXCNT = unsigned Constant Max of SLCNT * * Return: * * RVKE = bool result of timer function block * Returnaddress is RLINK+6 ! * * Side effects: * * Registers ;RDREF, RLINK are changed * * Note: These Subroutines constitute some of the most * frequent called code of plc programs. They are * optimised towards speed, therefore, hence violating * basic programming paradigms, particularly having * multiple exits. Sorry. * *----------------------------------------------------------- * IDT 'TIMERSUB' * Exports DEF TONS,TOFFS,TONOFS * External References REF SLCNT CurrentTime, 0 or 1 .. CNTMAX REF CNTMAX Maximal SLCNT * Register Usage RVKE EQU 0 ; RLO (Result of Logical Operation) ;RDREF EQU 9 ; Macro Dereferencing Register RLINK EQU 11 ; dedicated register return adrress * Parameter Offsets to RLINK KLIMIT EQU 0 offset TimeLimitConstant KMULTC EQU 2 offset TimeMultiplierConst * *----------------------------------------------------------- * * Timer Subroutine TONS * * Entry - testing for leading and trailing edge TONS MOVB RVKE,RVKE VKE == 0 ? JEQ FALED1 yes -> falling edge CB *;RDREF+,RVKE VKES == 0 ? (VKE=1 here) JNE RISED1 yes -> rising edge * compute elapsed time in RVKE MOV @SLCNT,RVKE RVKE := CurrentTime S *;RDREF,RVKE RVKE := CurrentTime - StartT JOC CP2LI1 if negative AI RVKE,CNTMAX adjust elapsed time * compare elapsed time to time limit CP2LI1 C RVKE,*RLINK compare to TimeLimit JHE DECML1 if reached -> decr. multcnt. * if time limit not reached return 0 ELAPS1 AI RLINK,6 adjust return address SZCB RVKE,RVKE Q := 0 RT * decrement multipl. counter if 0 -> time up else -> elapsed DECML1 DEC @2(;RDREF) decr. MultiplikatorCounter JEQ TIMUP1 MOV @SLCNT,*;RDREF reset StartTime JMP ELAPS1 * time is up, Q := 1 TIMUP1 AI RLINK,6 adjust return address DECT ;RDREF ;RDREF := &QS SETO *;RDREF QS := VKES := 1 MOVB *;RDREF,RVKE Q := 1 RT * rising edge: start timer with current time und multiplier RISED1 MOV @SLCNT,*;RDREF+ StartTime MOV @KMULTC(RLINK),*;RDREF Multiplier AI RLINK,6 adj. return address MOVB RVKE,@-3(;RDREF) VKES := 1 SZCB RVKE,RVKE Q := 0 RT * falling edge: Q := 0 FALED1 AI RLINK,6 adj. return address DEC ;RDREF ;RDREF := &QS CLR *;RDREF QS := VKES := 0 MOVB RVKE,RVKE set flags (Q is 0) RT * *----------------------------------------------------------- * * Timer Subroutine TOFFS * * Entry - testing for leading and trailing edge TOFFS MOVB RVKE,RVKE VKE == 1 ? JNE RISED2 yes -> rising edge CB *;RDREF+,RVKE VKES == 1 ? (VKE=0 here) JNE FALED2 yes -> falling edge * compute elapsed time in RVKE MOV @SLCNT,RVKE RVKE := CurrentTime S *;RDREF,RVKE RVKE := CurrentTime - StartT JOC CP2LI2 if negative AI RVKE,CNTMAX adjust elapsed time * compare elapsed time to time limit CP2LI2 C RVKE,*RLINK compare to TimeLimit JHE DECML2 if reached -> decr. multcnt. * if time limit not reached return 1 ELAPS2 AI RLINK,6 adjust return address ORI RVKE,>FF00 Q := 1 RT * decrement multipl. counter if 0 -> time up else -> elapsed DECML2 DEC @2(;RDREF) decr. MultiplikatorCounter JEQ TIMUP2 MOV @SLCNT,*;RDREF reset StartTime JMP ELAPS2 * time is up, Q := 0 TIMUP2 AI RLINK,6 adjust return address SZCB RVKE,RVKE Q := 0 MOVB RVKE,@-2(;RDREF) QS := 0 RT * falling edge: start timer with current time und multiplier FALED2 MOV @SLCNT,*;RDREF+ StartTime MOV @KMULTC(RLINK),*;RDREF Multiplier AI RLINK,6 adj. return address MOVB RVKE,@-3(;RDREF) VKES := 0 ORI RVKE,>FF00 Q := 1 RT * rising edge: Q := 1 RISED2 AI RLINK,6 adj. return address DEC ;RDREF ;RDREF := &QS SETO *;RDREF QS := VKES := 1 MOVB RVKE,RVKE set flags (Q is 1) RT * *----------------------------------------------------------- * * Timer Subroutine TONOFS * TONOFS CB RVKE,*;RDREF+ VKE != VKES ? JNE EDGE3 yes -> edge * compute elapsed time in RVKE MOV @SLCNT,RVKE RVKE := CurrentTime S *;RDREF,RVKE RVKE := CurrentTime - StartT JOC CP2LI3 if negative AI RVKE,CNTMAX adjust ElapsedTime * compare elapsed time to time limit CP2LI3 C RVKE,*RLINK compare to TimeLimit JHE DECML3 * if time limit not reached return QS ELAPS3 AI RLINK,6 adjust return address MOV @-2(;RDREF),RVKE Q := QS RT * decrement multipl. counter, if 0 -> time up else -> elapsd DECML3 DEC @2(;RDREF) --Multiplicatorcounter JEQ TIMUP3 MOV @SLCNT,*;RDREF reset StartTime JMP ELAPS3 * time is up, Q := VKES TIMUP3 AI RLINK,6 adjust return addr. MOVB @-1(;RDREF),RVKE Q := VKES MOVB RVKE,@-2(;RDREF) QS := Q RT * edge, away from QS: start timer EDGE3 MOVB RVKE,@-1(;RDREF) VKES := VKE MOV @SLCNT,*;RDREF+ StartTime MOV @KMULTC(RLINK),*;RDREF Multiplier AI RLINK,6 adjust return addr. MOVB @-4(;RDREF),RVKE Q := QS RT END