; ---------------------------------------------------------- ; ms2.asm - 2 channel memory switch ; (C) Claus Poltermann ; https://cp-elektronik.de ; ---------------------------------------------------------- ; Pin assignment: ; 0: jmp channel 1 input (oben) ; 1: channel 1 output ; 2: error LED output ; 3: receiver input ; 4: channel 2 output ; 5: jmp channel 2 input LIST p=12f629 include "p12f629.inc" __config _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _INTRC_OSC_NOCLKOUT ; definitions of variables cblock 0x20 activeCounter ; holds counter value for active pulse errorFlag ; indicates an error condition nrOfMeas activeCounterSumLo ; 16 bit register activeCounterSum activeCounterSumHi activeCounterAverage ; holds result of division counter ; universal counter register nrOfMeasToDo currentAction oldAction channel_1 channel_2 ; values for channels 1/2 to switch on errorCounter endc ; definitions of constant values maxActiveCounter equ 0xFF ; max value for activeCounter maxPassiveTimer equ 0xFF ; max value for TMRO during passive pulse maxErrorCounter equ 0xFF ; max. number of invalid receiver pulses ; until output is switched off org 0x00 goto main ; --- subroutine "waitForPassiveMode" wfpm clrf activeCounter clrf errorFlag wfpmLoop incf activeCounter, F ; test if activeCounter == maxActiveCounter movf activeCounter, W sublw maxActiveCounter btfss STATUS, Z goto acContinue bsf errorFlag, 0 ; set error flag return acContinue movf GPIO, F btfsc GPIO, 3 ; bit = 0 -> exit loop goto wfpmLoop return ; --- end subroutine "waitForPassiveMode" ; --- subroutine "waitForActiveMode" wfam clrf errorFlag clrf TMR0 wfamLoop ; test if TMR0 has reached max value movf TMR0, W sublw maxPassiveTimer btfss STATUS, Z goto PaContinue bsf errorFlag, 0 return PaContinue movf GPIO, F btfss GPIO, 3 ; bit = 1 -> exit loop goto wfamLoop call wfpm return ; --- end of subroutine waitForActiveMode ; --- subroutine "scan" scan movf GPIO, F btfss GPIO, 3 goto inputSignalLow call wfpm ; input Signal is high btfss errorFlag, 0 call wfam return inputSignalLow call wfam return ; --- end of subroutine scan ; --- subroutine "handleAction_0" handleAction_0 movf GPIO, F btfss GPIO, 0 ; GPIO = 1 means memory is activated bcf GPIO, 1 btfss GPIO, 5 bcf GPIO, 4 return ; --- end of subroutine "handleAction_0" ; --- subroutine "handleAction_1" handleAction_1 movlw B'00000010' xorwf GPIO, F ; invert GP0 btfss GPIO, 5 ; clear channel 2 if not in memory mode bcf GPIO, 4 return ;--- end of subroutine "handleAction_1" ; --- subroutine "handleAction_2" handleAction_2 movlw B'00010000' xorwf GPIO, F ; invert GP1 btfss GPIO, 0 ; clear channel 1 if not in memory mode bcf GPIO, 1 return ;--- end of subroutine "handleAction_2" ; --- subroutine "getActiveCounter" getActiveCounter begin call scan btfsc errorFlag, 0 goto scanError movf activeCounter, W ; activeCounterSum += activeCounter addwf activeCounterSumLo, F btfsc STATUS, C incf activeCounterSumHi, F incf nrOfMeas, F goto continue scanError bsf GPIO, 2 ; Error LED on clrf nrOfMeas clrf activeCounterSumLo clrf activeCounterSumHi incf errorCounter, F ; if errorCounter = maxErrorCounter movf errorCounter, W sublw maxErrorCounter btfss STATUS, Z goto continue ; then bcf GPIO, 1 ; channel 1 off bcf GPIO, 4 ; channel 2 off clrf oldAction ; oldAction = 0 clrf errorCounter continue ; test if nrOfMeas = nrOfMeasToDo movf nrOfMeas, W subwf nrOfMeasToDo, W btfss STATUS, Z goto begin bcf GPIO, 2 ; Error LED off clrf errorCounter return ; end of subroutine "getActiveCounter" ; --- main program main movlw 0x07 movwf CMCON ; disable comparator feature bsf STATUS, RP0 ; select Bank 1 errorlevel -302 call 3FFh ; calibrate internal oscillator movwf OSCCAL movlw B'01010111' ; timer mode, assign prescaler 1:256 to Timer0 movwf OPTION_REG bsf WPU, 0 ; enable pull up for memory config bsf WPU, 5 bcf WPU, 3 ; disable pull up RC input signal ; define output pins bcf TRISIO, 1 bcf TRISIO, 4 bcf TRISIO, 2 ; define input pins bsf TRISIO, 3 bsf TRISIO, 0 bsf TRISIO, 5 bcf STATUS, RP0 ; back to Bank 0 errorlevel +302 bsf GPIO, 2 ; Error LED on bcf GPIO, 1 ; channel 1 off bcf GPIO, 4 ; channel 2 off clrf nrOfMeas clrf activeCounterSumLo clrf activeCounterSumHi clrf errorCounter ; nrOfMeasToDo = 64 movlw D'64' movwf nrOfMeasToDo call getActiveCounter ; activeCounterSum / 64 ; take 2 MSB from lo byte ; and 6 LSB from hi byte clrf activeCounterAverage btfsc activeCounterSumLo, 6 bsf activeCounterAverage, 0 btfsc activeCounterSumLo, 7 bsf activeCounterAverage, 1 btfsc activeCounterSumHi, 0 bsf activeCounterAverage, 2 btfsc activeCounterSumHi, 1 bsf activeCounterAverage, 3 btfsc activeCounterSumHi, 2 bsf activeCounterAverage, 4 btfsc activeCounterSumHi, 3 bsf activeCounterAverage, 5 btfsc activeCounterSumHi, 4 bsf activeCounterAverage, 6 btfsc activeCounterSumHi, 5 bsf activeCounterAverage, 7 ; channel_1 = average + 25 movlw D'25' addwf activeCounterAverage, W movwf channel_1 ; channel_2 = average - 25 movlw D'25' subwf activeCounterAverage, W movwf channel_2 ; oldAction = 0 clrf oldAction ; nrOfMeasToDo = 16 movlw D'16' movwf nrOfMeasToDo mainLoop clrf nrOfMeas clrf activeCounterSumLo clrf activeCounterSumHi call getActiveCounter ; activeCounterAverage = activeCounterSum / 16 ; take 4 MSB from lo byte ; and 4 LSB from hi byte clrf activeCounterAverage btfsc activeCounterSumLo, 4 bsf activeCounterAverage, 0 btfsc activeCounterSumLo, 5 bsf activeCounterAverage, 1 btfsc activeCounterSumLo, 6 bsf activeCounterAverage, 2 btfsc activeCounterSumLo, 7 bsf activeCounterAverage, 3 btfsc activeCounterSumHi, 0 bsf activeCounterAverage, 4 btfsc activeCounterSumHi, 1 bsf activeCounterAverage, 5 btfsc activeCounterSumHi, 2 bsf activeCounterAverage, 6 btfsc activeCounterSumHi, 3 bsf activeCounterAverage, 7 ; test if activeCounterAverage > channel_1 ? movf activeCounterAverage, W subwf channel_1, W ; channel_1 - activeCntAvg btfsc STATUS, C ; C=0: activeCntAvg > channel_1 goto no1 movlw 0x01 movwf currentAction ; currentAction = 1 goto cont1 no1 ; test if activeCounterAverage < channel_2 ? movf channel_2, W subwf activeCounterAverage, W ; activeCntAvg - channel_2 btfsc STATUS, C ; C=0: channel_2 > activeCntAvg goto no2 movlw 0x02 movwf currentAction ; currentAction = 2 goto cont1 no2 clrf currentAction ; currentAction = 0 cont1 ; currentAction == oldAction ? movf currentAction, W subwf oldAction, W btfsc STATUS, Z ; Z=0 : currentAction != oldAction goto mainLoop ; currentAction differs from oldAction ; test if currentAction == 1 btfss currentAction, 0 goto no3 call handleAction_1 goto cont2 no3 ; test if currentAction == 2 btfss currentAction, 1 goto no4 call handleAction_2 goto cont2 no4 call handleAction_0 cont2 movf currentAction, W movwf oldAction ; oldAction = currentAction goto mainLoop end