TITLE "Slave2" LIST p=16F870,n=0 __CONFIG 0x0C02 ; ; Prototype slave software Version 2 ; Derived from version 1.3 ; Version 2.0 : new identification of slave ; Version 2.1 : numbering of displays has been modified ; Version 2.2 : more efficient state machines ; Version 3.0 : All state machines rewritten and debugged ; ; Configured for variable pump control through command 3. ; Version pc 10 : Fully tested, control range 14H to D0H ; Version pc 11 : control range : 0 to BCH, Display gives firing delay in % of 10 ms. ; ; ;PIC SPECIAL FUNCTION REGISTERS ;BANK 0 ; INDF EQU 0x00 ; TMR0 EQU 0x01 ;Timer 0 register PCL EQU 0x02 ;Program Counter register (8 least significant bits) STATUS EQU 0x03 ;Status register FSR EQU 0x04 ; PORTA EQU 0x05 ;Port A register PORTB EQU 0x06 ;Port B register : all for LED displays PORTC EQU 0x07 ;Port C register PCLATH EQU 0x0A ;PCLATH register INTCON EQU 0x0B ;Interrupt Control Register PIR1 EQU 0x0C ;Peripheral Interrupt Flag register PIR2 EQU 0x0D ; TMR1L EQU 0x0E ; TMR1H EQU 0x0F ; T1CON EQU 0x10 ; TMR2 EQU 0x11 ; T2CON EQU 0x12 ; CCPR1L EQU 0x15 ; CCPR1H EQU 0x16 ; CCP1CON EQU 0x17 ; RCSTA EQU 0x18 ;USART Receive Setup register TXREG EQU 0x19 ;USART Transmit Data register RCREG EQU 0x1A ;USART Receive Data register ADRESH EQU 0x1E ; ADCON0 EQU 0x1F ;AD Converter 0 register ; ;BANK1 ;----- OPTION_REG EQU 0x81 ;Option register TRISA EQU 0x85 ;Port A Setup register TRISB EQU 0x86 ;Port B Setup register TRISC EQU 0x87 ;Port C Setup register PIE1 EQU 0x8C ;Peripheral Interrupt Control register 1 PIE2 EQU 0x8D ; PCON EQU 0x8E ; PR2 EQU 0x92 ; TXSTA EQU 0x98 ;USART Transmit Setup register SPBRG EQU 0x99 ;USART Baudrate Generator register ADRESL EQU 0x9E ; ADCON1 EQU 0x9F ;AD Convertor register 1 ;Instruction qualifier symbols W EQU 0x00 ;Specifies that result has to go into W F EQU 0x01 ;Specifies result has to stay in register file C EQU 0x00 ;Refers to the C bit in the status register Z EQU 0x02 ;Refers to the Z bit in the status register ;CONTEXT SAVING REGISTERS (should be in the last 16 bytes of memory page) W_TEMP EQU 0x70 ;W register buffer STAT_TEMP EQU 0x71 ;STATUS reg buffer PCLH_TEMP EQU 0x72 ;PCLATH reg buffer ; GENERAL PURPOSE AND FSM REGISTERS TEMP EQU 0x20 ;General Purpose Temporary register TEMP_COM EQU 0x21 ;Temporary command register TEMP_DAT EQU 0x22 ;Temporary data register RX_BUF EQU 0x23 ;Buffer for received data RX_COM EQU 0x24 ;Command register RX_DAT EQU 0x25 ;Data register TX EQU 0x26 ;Transmit register BFSM EQU 0x27 ;Bus Finite State Machine register DFSM EQU 0x28 ;Display Finite State Machine register TFSM EQU 0x29 ;Transmitter Finite State Machine register AFSM EQU 0x2A ;AD Converter Finite State Machine register PFSM EQU 0x2B ;Pump power control Finite State Machine register PDELAY EQU 0x2C ;Delay before firing the triac ID EQU 0x2E ;4 bit address of module (stored in 4 MSB's) CONTROL EQU 0x2F ;Control word for communicating inside slave program ;D7: Character received by usart ;D4: Transmission required ;D3: Broadcast received ;D2: New command received ;D1: Condition Test Flag bit ;D0: TMR0 Overflow Flag bit ; ;MASTER MODULE REGISTERS ; DISP_0 EQU 0x30 ;Display 0 register (7 seg.msd) DISP_1 EQU 0x31 ;Display 1 register (7 seg.lsd) DISP_2 EQU 0x32 ;Display 2 register DISP_3 EQU 0x33 ;Display 3 register DTIME_0 EQU 0x34 ;Delay counter for display 0 DTIME_1 EQU 0x35 ;Delay counter for display 1 DTIME_2 EQU 0x36 ;Delay counter for display 2 DTIME_3 EQU 0x37 ;Delay counter for display 3 DTIME_OFF EQU 0x38 ;Delay counter for display ADVAL EQU 0x39 ;Rounded AD value AD_DIG_0 EQU 0x3A ;least significant digit of AD value AD_DIG_1 EQU 0x3B ;Most significant digit of AD value RANGE EQU 0x3C ;Range for ADVAL decimal conversion DIG_OUT EQU 0x3D ;Temporary variable for digital output ; ;SYNCHRONIZATION SYMBOLS SYNC_M EQU 0x0A ;Change direction / Synchronize slaves SYNC_S EQU 0x0D ;Synchronize slaves ;Display delays DDELAY_0 EQU 0x20 DDELAY_1 EQU 0x20 DDELAY_2 EQU 0x08 DDELAY_3 EQU 0x08 DDELAY_OFF EQU 0x01 DEC_RANGE EQU 0x87 ; Range for delay: 10 ms = 100 % INITDELAY EQU 0x14 ; Offset for compensating phase and delay in 50Hz sync. ; ; *** Begin of executable code. ; ORG 0x00 ; GOTO START ; ORG 0x04 ; ; ; Interrupt handler (interrupts are now disabled, comments start with =) ; INTER MOVWF W_TEMP ;=Place W register content in W_TEMP register SWAPF STATUS,0 ;=Swap STATUS register in W register CLRF STATUS ;=Make sure the interrupt driver starts in bank 0 MOVWF STAT_TEMP ;=Save STATUS register in STAT_TEMP register MOVF PCLATH,0 ;=Copy PCLATH register in W register MOVWF PCLH_TEMP ;=Save PCLATH register in PCLH_TEMP register CLRF PCLATH ;=make sure PCLATH contains 0 at this point BTFSC PIR1,2 ;=Interrupt from the RC2 50 Hz signal ? GOTO CCP_INT ;=Yes, start delay for triac trigering BTFSC PIR1,5 ;=Check if USART Buffer is full GOTO USART_INT ;=USART Buffer is full, process USART interrupt BTFSC INTCON,2 ;=Check if TMR0 overflow occured GOTO TMR0_INT ;=TMR0 overflow occured, process TMR0 interrupt ;=Jump to INTER_END routine (spurious interrupt !!!) ; ; End of interrupt handler ; INTER_END MOVF PCLH_TEMP,0 ;=Restore original PCLATH register MOVWF PCLATH BCF PORTA,1 ;=the triac command has to be switched off now SWAPF STAT_TEMP,0 ;=Restore original STATUS register MOVWF STATUS ;= SWAPF W_TEMP,1 ;=Restore original W register SWAPF W_TEMP,0 ;= RETFIE ;=Return and reenable interrupts ; ; Computed GOTO statements. ; The code of these statements should never cross a page boundary ; therefor they are all grouped here in page 0 ; ; 7 segment decoder BCD code in W, at return 7 segment code in W ; SEVENSEG CLRF PCLATH ;Make sure PCLATH contains 0 (always here) ADDWF PCL,F ;Jump to appropriate number RETLW 0x7E ;0 RETLW 0x0C ;1 RETLW 0xB6 ;2 RETLW 0x9E ;3 RETLW 0xCC ;4 RETLW 0xDA ;5 RETLW 0xFA ;6 RETLW 0x0E ;7 RETLW 0xFE ;8 RETLW 0xDE ;9 ; TXFSM ; Computed goto statement for Transmitter Finite State machine ; CLRF PCLATH ;Make sure PCLATH contains 0 (always here) MOVF TFSM,W ;Get the FSM variable ADDWF PCL,F ;Perform a computed GO TO GOTO TSTATE_0 ;Wait for bus and send Sync_S GOTO TSTATE_1 ;Wait for room in TXREG GOTO TSTATE_2 ;Send TX_COM GOTO TSTATE_3 ;Wait for room in TXREG GOTO TSTATE_4 ;Send TX_DAT GOTO TSTATE_5 ;Wait for completion and reset everything ; DPFSM ; Computed goto statement for Display Finite State machine ; CLRF PCLATH ;Make sure PCLATH contains 0 (always here) MOVF DFSM,W ;Get the FSM variable ADDWF PCL,F ;Perform a computed GO TO GOTO DSTATE_00 ;display most significant digit GOTO DSTATE_01 ; GOTO DSTATE_02 ; GOTO DSTATE_03 ; GOTO DSTATE_04 ; GOTO DSTATE_05 ; GOTO DSTATE_06 ; GOTO DSTATE_07 ; GOTO DSTATE_08 ; GOTO DSTATE_09 ; ; BSFSM ; Computed goto statement for Bus Slave Finite State machine ; CLRF PCLATH ;=Make sure PCLATH contains 0 (always here) MOVF BFSM,W ;=Get the FSM variable ADDWF PCL,F ;=Perform a computed GO TO GOTO BSTATE_00 ;= GOTO BSTATE_01 ;= GOTO BSTATE_02 ;= GOTO BSTATE_03 ;= GOTO BSTATE_04 ;= GOTO BSTATE_05 ;= GOTO BSTATE_06 ;= GOTO BFSMOUT ;=State 07 is transient, so this should never occur. GOTO BSTATE_08 ;= ; BFSMOUT ; Computed goto statement for Bus Slave Finite State machine output ; CLRF PCLATH ;=Make sure PCLATH contains 0 (always here) MOVF BFSM,W ;=Get the FSM variable ADDWF PCL,F ;=Perform a computed GO TO GOTO INTER_END ;=Nothing to do in this state GOTO INTER_END ;=Nothing to do in this state GOTO INTER_END ;=Nothing to do in this state GOTO INTER_END ;=Nothing to do in this state GOTO INTER_END ;=Nothing to do in this state GOTO OUT_05 ;= GOTO OUT_06 ;= GOTO OUT_07 ;= GOTO INTER_END ;=Nothing to do in this state ; PCFSM ; Computed goto statement for Pump Control Finite State machine. ; CLRF PCLATH ;=Make sure PCLATH contains 0 (always here) MOVF PFSM,W ;=Get the FSM variable ADDWF PCL,F ;=Perform a computed GO TO GOTO INTER_END ;=No pump control, spurious interrupt GOTO PFSM_1 ;=Delay before first firing is now over GOTO PFSM_2 ;=Delay before second firing is now over ; ; End of the computed gotos for finite state machines ; ; ************************************************************************************************* ; ORG 0x0100 ;Begin of code that doesn't need to be in page 0 ; START ;INTCON REGISTER INITIALIZATION BCF INTCON,7 ;Disable all interrupts BSF INTCON,6 ;Enable all peripheral interrupts BCF INTCON,5 ;Disable TMR0 overflow interrupt BCF INTCON,4 ;Disable RB0/INT external interrupt BCF INTCON,3 ;Disable RB port change interrupt BCF INTCON,2 ;Clear TMR0 overflow interrupt flag bit BCF INTCON,1 ;Clear RB0 interrupt flag bit BCF INTCON,0 ;Clear RB port change interrupt flag bit ; ; OPTION REGISTER INITIALIZATION ; BSF STATUS,5 ;Switch to BANK1 BSF OPTION_REG,7 ;Disable PORTB Pull-ups * BSF OPTION_REG,6 ;Interrupt on rising edge of RB0/INT BCF OPTION_REG,5 ;Enable internal instruction cycle clock BCF OPTION_REG,4 ;Increment TMR0 on low-to-high transition BCF OPTION_REG,3 ;Assign prescaler to TMR0 BSF OPTION_REG,2 ;\ BSF OPTION_REG,1 ;|Configure prescaler as 1:256 BSF OPTION_REG,0 ;/ BCF STATUS,5 ;Switch to BANK0 ; ; PIR1 Register initialization ; CLRF PIR1 ; Reset all peripheral interrupt flags ; ;PIE1 REGISTER INITIALIZATION BSF STATUS,5 ;Switch to BANK1 BCF PIE1,7 ;Disable PSP-read/write-interrupt BCF PIE1,6 ;Disable AD-CONVERTOR interrupt BSF PIE1,5 ;Enable USART-RECEIVE interrupt BCF PIE1,4 ;Disable the USART-TRANSMIT interrupt BCF PIE1,2 ;Disable CCP1 interrupt BCF PIE1,1 ;Disable TMR2=PR2 interrupt BCF PIE1,0 ;Disable TMR1 interrupt BCF STATUS,5 ;Switch to BANK0 ; ;IO REGISTER INITIALIZATION CLRF PORTA ;Initialize PORTA CLRF PORTB ;Initialize PORTB CLRF PORTC ;Initialize PORTC BSF STATUS,5 ;Switch to BANK1 MOVLW 0x01 ;00000001 in W-REG MOVWF TRISA ;PORTA : all outputs except A0, analog input MOVLW 0x00 ;00000000 in W-REG MOVWF TRISB ;All outputs PORTB MOVLW 0x84 ;10000100 in W-REG MOVWF TRISC ;RC7,2 is input, RC6,5,4,3,1,0 are outputs. ; C0 : Bus transmit enable ; C1 : Display 0 enable ; C2 : 50 Hz input from pump control ; C3 : Display 1 enable ; C4 : Display 2 enable ; C5 : Display 3 enable ; C6 : USART output ; C7 : USART input MOVLW 0x0E ;00001110 in W-REG MOVWF ADCON1 ;AD converter: 1 ch. A0, ref = Vdd and Vss, res left justif. BCF STATUS,5 ;Switch to BANK0 MOVLW 0x05 ; Capture mode interrupt on climbing edge of RC2 MOVWF CCP1CON ; by loading 05H in the CCP1CON register ;TXSTA REGISTER INITIALIZATION BSF STATUS,5 ;Switch to BANK1 BCF TXSTA,7 ;Asynchronous mode BCF TXSTA,6 ;8 bit mode BSF TXSTA,5 ;Transmit enabled BCF TXSTA,4 ;Asynchronous mode select BSF TXSTA,2 ;High speed mode BCF STATUS,5 ;Switch to BANK0 ;RCSTA REGISTER INITIALIZATION BSF RCSTA,7 ;Serial port enabled BCF RCSTA,6 ;8 bit mode BCF RCSTA,5 ;Single receive disabled BSF RCSTA,4 ;Continuous receive enabled BCF RCSTA,3 ;Address detection disabled ;SPBRG REGISTER INITIALIZATION BSF STATUS,5 ;Switch to BANK1 MOVLW 0x40 ;01000000 MOVWF SPBRG ;Initialize Bit rate (19200 b/s) ---> 20 MHz crystal BCF STATUS,5 ;Switch to BANK0 ;COMMUNICATION BUS INITIALIZATION BCF PORTC,0 ;Bus direction starts in receive mode ('0') CLRF RX_COM ;Receiver buffers initially 0 CLRF RX_DAT ;FSM & CONTROL REGISTER INITIALIZATION CLRF BFSM ;Clear the BFSM register (Bus State 0) CLRF DFSM ;Clear the DFSM register (Display state 0) CLRF TFSM ;Clear the TFSM register (Tx state 0) CLRF AFSM ;Clear the AFSM register (ADC state 0) CLRF PFSM ;Clear the PFSM register (Pump state 0) CLRF CONTROL ;Clear the Control register ;ID REGISTER INITIALIZATION FROM DIP switches (specific for new slave hardware). BSF STATUS,5 ;Switch to BANK1 MOVLW 0xBE ;10111110 in W register MOVWF TRISC ;Set pins as input for reading ID BCF STATUS,5 ;Switch to BANK0 CLRF ID ;Clear ID register CLRF PORTB ;Make sure all led's are off BSF PORTA,5 ;Pull up ID_SENSE pin (start scanning address) BTFSS PORTC,1 ;Check if first ID bit is set (ACTIVE LOW) BSF ID,4 ;Set bit in ID BTFSS PORTC,3 ;Check if second ID bit is set (ACTIVE LOW) BSF ID,5 ;Set bit in ID BTFSS PORTC,4 ;Check if third ID bit is set (ACTIVE LOW) BSF ID,6 ;Set bit in ID BTFSS PORTC,5 ;Check if fourth ID bit is set (ACTIVE LOW) BSF ID,7 ;Set bit in ID BSF STATUS,5 ;Switch to BANK1 MOVLW 0x84 ;10000100 in W register MOVWF TRISC ;Set pins back to original state BCF STATUS,5 ;Switch to BANK0 BCF PORTA,5 ;Pull down ID_SENSE pin ;DISPLAY REGISTER INITIALIZATION ; MOVLW 0x3A ;Turn all displays off (active low) IORWF PORTC,F ; CLRF AD_DIG_0 ;Clear initial value of decimal AD value CLRF AD_DIG_1 ;to avoid spurious 7 seg display ; BSF INTCON,7 ;Enable Global Interrupts ; ; ; Main program loop. ; MAIN ; ; Display control ; MOVF RX_COM,W ;Display received command on the LEDS's MOVWF DISP_2 MOVF RX_DAT,W MOVWF DISP_3 CALL DECCONV ; Convert ADVAL into two decimal numbers MOVF AD_DIG_0,W ; Display AD value on digital displays MOVWF DISP_1 MOVF AD_DIG_1,W MOVWF DISP_0 ; ; Command decoding ; BTFSS CONTROL,2 ;Command received ? GOTO MAIN_1 ;No command received BCF CONTROL,2 ;New command has been detected, reset it MOVLW 0x0F ;Prepare for masking bus address on command ANDWF RX_COM,0 ;Command nibble is now in W BTFSC STATUS,Z ;Is command all 0 (=Reset?) GOTO START ; 0: RESET everything !!! BTFSS CONTROL,3 ;check for broadcast BSF CONTROL,4 ;Reply to all commands except a broadcasted one SUBLW 0x03 ;Is it command 3, variable speed pump control ? BTFSS STATUS,Z ; GOTO MAIN_1 ;NO, but this slave only understands command 3. ;YES, Command 3 handling ; ; C2 receives pulses synchronous with 50 Hz (as close as possible to 0 crossing) ; A1 : controls triac trigger (two pulses at 10 ms from each other per period) ; MOVF RX_DAT,W ; Get new delay value ADDLW INITDELAY ; Add offset for compensating transformer phase MOVWF PDELAY ; and store it in PDELAY for controling the timer MOVWF ADVAL ; and in ADVAL for controling the decimal display MOVF PFSM,F ; Proportional motor control already enabled ? BTFSS STATUS,Z ; PFSM = 0 means that proportional control is off GOTO MAIN_1 ; Already enabled, so this main program has nothing more to do INCF PFSM,F ; Not yet enabled, so enable it ! BCF INTCON,5 ; Disable TMR 0 interrupts MOVLW 0x05 ; Capture mode interrupt on falling edge of RC2 MOVWF CCP1CON ; by loading 05H in the CCP1CON register BCF PIR1,2 ; Reset CCP interrupt flag BSF STATUS,5 ; Switch to bank 1 BSF PIE1,2 ; Enable interrupt from RC2 BCF STATUS,5 ; and switch back to bank 0 ; MAIN_1 ; Transmitter control ; BTFSS CONTROL,4 ;Transmission required ? GOTO MAIN_2 ;No transmission required ; ; The transmitter is controlled by a finite state machine. ; CALL TXFSM MAIN_2 ; Display control (by a finite state machine) ; CALL DPFSM GOTO MAIN ; ; DECCONV ; Subroutine to convert binary data into two digits ; MOVLW DEC_RANGE ; load decimal range in RANGE variable MOVWF RANGE CLRF AD_DIG_0 ; Initial value of product = 0 MOVLW 0x08 ; Prepare for loop with 8 steps MOVWF TEMP MOVF ADVAL,W ; Get value to be converted MULLOOP BCF STATUS,C ; explore one by one bits of RANGE RRF RANGE,F ; BTFSC STATUS,C ; if one, add value to be converted to product ADDWF AD_DIG_0,F ; RRF AD_DIG_0,F ; rotate product one position to the right DECFSZ TEMP,F ; check if one more loop needed GOTO MULLOOP MOVLW 0x0A ; prepare division by 10 CLRF AD_DIG_1 ; Initial value of MSD = 0 DIVLOOP INCF AD_DIG_1,F SUBWF AD_DIG_0,F ; BTFSC STATUS,C ; Check if result of GOTO DIVLOOP ; DECF AD_DIG_1,F ; (ADVAL * RANGE div 256) div 10 now in AD_DIG_1 ADDWF AD_DIG_0,F ; (ADVAL * RANGE div 256) mod 10 now in AD_DIG_1 RETURN ; ; Transmitter control Finite State Machine ; TSTATE_0 ; Wait till Bus available and then transmit Sync_S MOVF BFSM,0 ; Get Bus state SUBLW 0x08 ; Check if in wait state BTFSS STATUS,2 ; RETURN ; Not yet ; BSF PORTC,0 ; OK,Set bus in transmit mode MOVLW SYNC_S ; prepare transmission of SYNC_S MOVWF TXREG ; Send it to transmit buffer INCF TFSM,F ; Set state 1 RETURN ; TSTATE_1 ; Wait till TXREG again empty BTFSS PIR1,4 ; Check if TXREG empty RETURN ; Not yet, stay in state 1 INCF TFSM,F ; Yes, set state 2 RETURN ; TSTATE_2 ; Transmit TX_COM SWAPF ID,0 ; Put slave ID in COM field MOVWF TXREG ; Send TX_COM to transmit buffer INCF TFSM,F ; Set state 3 RETURN ; TSTATE_3 ; Wait till TXREG again empty BTFSS PIR1,4 ; Check if TXREG empty RETURN ; Not yet, stay in state 3 INCF TFSM,F ; Yes, set state 4 RETURN ; TSTATE_4 ; Transmit TX_DAT MOVF ADVAL,0 ; Get most recent result of AD conversion MOVWF TXREG ; Put it into the transmit buffer INCF TFSM,F ; Set state 5 RETURN ; TSTATE_5 ; Wait till transmission completed BSF STATUS,5 ; Access register bank 1 BTFSC TXSTA,1 ; Check the transmitter empty bit GOTO TSTATE_51 ; Empty, Reset evrything BCF STATUS,5 ; Not yet empty, reset register bank 0 RETURN ; and keep waiting in state 5 TSTATE_51 BCF STATUS,5 ; Reset register bank 0 BCF PORTC,0 ; Set bus back in receive mode BCF CONTROL,4 ; Clear transmission required bit CLRF TFSM ; Reset transmission state machine RETURN ; ; Analog to digital control Finite State Machine ; ASTATE_0 ; Sample channel 0 MOVLW 0x81 ; select ch.0 and switch on sample and hold. MOVWF ADCON0 INCF AFSM,1 ; go to state 1 RETURN ; ASTATE_1 ; Start conversion MOVLW 0x85 ; Start the conversion MOVWF ADCON0 INCF AFSM,1 ; GO to state 2 RETURN ; ASTATE_2 ; Wait till conversion done BTFSC ADCON0,2 ; Test if done RETURN ; Not yet INCF AFSM,1 ; Done, go to state 3 RETURN ; ASTATE_3 ; Store results MOVF ADRESH,0 ; MSB in W BSF STATUS,5 ; access register bank 1 BTFSC ADRESL,7 ; Check msb of lower byte ADDLW 0x01 ; Round the value in W BCF STATUS,5 ; access register bank 0 MOVWF ADVAL ; store rounded result CLRF AFSM ; reset to state 0 RETURN ; ; Display Finite State Machine ; DSTATE_00 ; state 0 : switch on most significant digit ; MOVLW DDELAY_0 ;Initialise On delay for display 0 MOVWF DTIME_0 MOVF DISP_0,0 ;Place DISP_0 register in W register CALL SEVENSEG ;convert bcd into 7-segment code MOVWF PORTB ;Place W register on PORTB BCF PORTC,1 ;Switch on display 0. INCF DFSM,1 ;Increment DFSM register to state 01 RETURN ; and return to main program ; DSTATE_01 ; state 1 : most significant digit stays on until DTIME_0 reaches 0. ; DECFSZ DTIME_0,F ;Time over ? RETURN ; Not yet, stay in state 1, and finish display handling INCF DFSM,1 ; Yes, Increment DFSM to state 2 RETURN ; and return to main program ; DSTATE_02 ; state 2 : switch on least significant digit ; MOVLW DDELAY_1 ;Initialise On delay for display 1 MOVWF DTIME_1 BSF PORTC,1 ;Switch off display 0. MOVF DISP_1,0 ;Place DISP_1 register in W register CALL SEVENSEG ;convert bcd into 7-segment code MOVWF PORTB ;Place W register on PORTB BCF PORTC,3 ;Switch on display 1. INCF DFSM,1 ;Increment DFSM register to state 03 RETURN ; and return to main program ; DSTATE_03 ; state 3 : least significant digit stays on until DTIME_1 reaches 0. ; DECFSZ DTIME_1,F ;Time over ? RETURN ; Not yet, stay in state 3, and finish display handling INCF DFSM,1 ; Yes, Increment DFSM to state 4 RETURN ; and return to main program ; DSTATE_04 ; state 4 : switch on command leds display ; MOVLW DDELAY_2 ;Initialise On delay for display 2 MOVWF DTIME_2 BSF PORTC,3 ;Switch off display 1. MOVF DISP_2,0 ;Place DISP_2 register in W register MOVWF PORTB ;Place W register in PORTB BCF PORTC,4 ;Switch on display 2. INCF DFSM,1 ;Increment DFSM register to state 05 RETURN ; and return to main program ; DSTATE_05 ; state 5 : command leds stay on until DTIME_2 reaches 0. ; DECFSZ DTIME_2,F ;Time over ? RETURN ; Not yet, stay in state 3, and finish display handling INCF DFSM,1 ; Yes, Increment DFSM to state 2 RETURN ; and return to main program ; DSTATE_06 ; state 6 : switch on data leds display ; MOVLW DDELAY_3 ;Initialise On delay for display 3 MOVWF DTIME_3 BSF PORTC,4 ;Switch off display 2. MOVF DISP_3,0 ;Place DISP_2 register in W register MOVWF PORTB ;Place W register in PORTB BCF PORTC,5 ;Switch on display 3. INCF DFSM,1 ;Increment DFSM register to state 07 RETURN ; and return to main program ; DSTATE_07 ; state 7 : data leds stay on until DTIME_3 reaches 0. ; DECFSZ DTIME_3,F ;Time over ? RETURN ; Not yet, stay in state 7, and finish display handling INCF DFSM,1 ; Yes, Increment DFSM to state 2 RETURN ; and return to main program ; DSTATE_08 ; state 8 :Switch off all displays ; MOVLW DDELAY_OFF MOVWF DTIME_OFF BSF PORTC,5 ;Switch off display 3. INCF DFSM,1 ;Increment DFSM register to state 05 RETURN ; and return to main program ; DSTATE_09 ; state 6 : All displays stay off until DTIME_OFF reaches 0. ; DECFSZ DTIME_OFF,F ;Time over ? RETURN ; Not yet, stay in state 9, and finish display handling CLRF DFSM ; Yes, Reset DFSM to state 0 RETURN ; and return to main program ; USART_INT ;Process USART interrupt ; BCF PIR1,5 ;=Clear USART Receive Interrupt Flag bit ; BTFSS RCSTA,1 ;=Check for overrun error GOTO USRT_INT1 ;=No overrun ; ; Overrun Condition ; MOVF RCREG,W ;=Empty Fifo MOVF RCREG,W ;=Empty Fifo MOVF RCREG,W ;=Extra empty ... BCF RCSTA,4 ;=Reset RX Module NOP ;=Do nothing BSF RCSTA,4 ;=Continue... GOTO INTER_END ;=Nothing more to do with USART ; USRT_INT1 ; No overrun error occured ; BTFSS RCSTA,2 ;=Check for framing error (no stop bit) GOTO USRT_INT2 ;=No framing error ; ; Framing Error Condition ; MOVF RCREG,W ;=Dummy read , no saving GOTO INTER_END ;=Nothing more to do with USART ; USRT_INT2 ; No overrun nor framing error occured, received byte should be OK! ; MOVF RCREG,W ;=Place received byte in W register MOVWF RX_BUF ;=Store received byte in RX_BUF register BSF CONTROL,7 ;=reactivate USART receiver GOTO BSFSM ;=Update now the bus fsm. ; ; ********* BusSlave Finite State Machine ****************************************************** ; ; Find present state and perform any needed transitions ; BSTATE_00 ;=Idle State CALL CONDIT_01 ;=Sync-S received ? BTFSC CONTROL,1 ;= INCF BFSM,1 ;=Yes, Increment BFSM register to state 01 GOTO BFSMOUT ;=Perform actions required in present state ; BSTATE_01 ;=Slave Initialisation step 1. CALL CONDIT_01 ;=Sync-S received ? BTFSC CONTROL,1 ;= INCF BFSM,1 ;=Yes, Increment BFSM register to state 02 CALL CONDIT_03 ;=Anything different from Sync-S received ? BTFSC CONTROL,1 ;= CLRF BFSM ;=Yes, Reset BFSM register to state 00 GOTO BFSMOUT ;=Perform actions required in present state ; BSTATE_02 ;=Slave Initialisation step 2. CALL CONDIT_01 ;=Sync-S received ? BTFSC CONTROL,1 ;= INCF BFSM,1 ;=Yes,Increment BFSM register to state 03 CALL CONDIT_03 ;=Anything different from Sync-S received ? BTFSC CONTROL,1 ;= CLRF BFSM ;=Yes, Reset BFSM register to state 00 GOTO BFSMOUT ;=Perform actions required in present state ; BSTATE_03 ;=Slave Initialisation step 3. CALL CONDIT_00 ;=Sync-M received ? BTFSS CONTROL,1 ;= GOTO BS_03_1 ;= INCF BFSM,1 ;=Yes, Increment BFSM register to state 4 GOTO BFSMOUT ;=Perform actions required in present state BS_03_1 CALL CONDIT_01 ;=Sync-S received ? BTFSC CONTROL,1 ;= GOTO BFSMOUT ;=Yes, stay in state 3 CALL CONDIT_02 ;=No, Anything different from Sync-M received ? BTFSC CONTROL,1 ;= CLRF BFSM ;=Yes, Reset BFSM register to state 0 GOTO BFSMOUT ;=Perform actions required in present state ; BSTATE_04 ;=Slave synchronization state CALL CONDIT_01 ;=Sync-S received ? BTFSC CONTROL,1 ;= INCF BFSM,1 ;=Yes, Increment BFSM register to state 05 GOTO BFSMOUT ;=Perform actions required in present state BSTATE_05 ;=Slave receive command state CALL CONDIT_03 ;=Anything different from Sync-S received ? BTFSC CONTROL,1 ;= INCF BFSM,1 ;=Yes,Increment BFSM register to state 06 CALL CONDIT_01 ;=Sync-S received ? BTFSC CONTROL,1 ;= CALL SETBFSM_02 ;=Yes, go back to state 2 GOTO BFSMOUT ;=Perform actions required in present state BSTATE_06 ;=Slave receive data state CALL CONDIT_04 ;=Any byte (data byte) received ? BTFSC CONTROL,1 ;= INCF BFSM,1 ;=Yes, set state 7 (transient state) GOTO BFSMOUT ;=Perform actions required in present state BSTATE_08 ;=Slave waiting for new commands state CALL CONDIT_01 ;=Sync-S received ? BTFSC CONTROL,1 ;= CALL SETBFSM_05 ;=Yes, go back to state 5 GOTO BFSMOUT ;=Perform actions required in present state SETBFSM_02 MOVLW 0x02 ;=Place literal in W register MOVWF BFSM ;=Store literal in BFSM register RETURN ;=Return to parent routine SETBFSM_05 MOVLW 0x05 ;=Place literal in W register MOVWF BFSM ;=Store literal in BFSM register RETURN ;=Return to parent routine ; ; CONDITIONS for state transitions ; CONDIT_00 ;=SYNC_M received ? BCF CONTROL,1 ;=Clear Condition Test Flag bit BTFSS CONTROL,7 ;=Check for new RX RETURN ;=No new RX -> leave subroutine MOVLW SYNC_M ;=Place SYNC_M symbol in W register SUBWF RX_BUF,0 ;=Compare SYNC_M symbol with received byte BTFSC STATUS,2 ;=Check if match GOTO COND_OK ;=Condition is true RETURN ;=Return to parent routine CONDIT_01 ;=SYNC_S received ? BCF CONTROL,1 ;=Clear Condition Test Flag bit BTFSS CONTROL,7 ;=Check for new RX RETURN ;=No new RX -> leave subroutine MOVLW SYNC_S ;=Place SYNC_S symbol in W register SUBWF RX_BUF,0 ;=Compare SYNC_S symbol with received byte BTFSC STATUS,2 ;=Check if match GOTO COND_OK ;=Condition is true RETURN ;=Return to parent routine CONDIT_02 ;=!SYNC_M received ? BCF CONTROL,1 ;=Clear Condition Test Flag bit BTFSS CONTROL,7 ;=Check for new RX RETURN ;=No new RX -> leave subroutine MOVLW SYNC_M ;=Place SYNC_M symbol in W register SUBWF RX_BUF,0 ;=Compare SYNC_M symbol with received byte BTFSS STATUS,2 ;=Check if no match GOTO COND_OK ;=Condition is true RETURN ;=Return to parent routine CONDIT_03 ;=!SYNC_S received ? BCF CONTROL,1 ;=Clear Condition Test Flag bit BTFSS CONTROL,7 ;=Check for new RX RETURN ;=No new RX -> leave subroutine MOVLW SYNC_S ;=Place SYNC_S symbol in W register SUBWF RX_BUF,0 ;=Compare SYNC_S symbol with received byte BTFSS STATUS,2 ;=Check if no match GOTO COND_OK ;=Condition is true RETURN ;=Return to parent routine CONDIT_04 ;=BYTE received BCF CONTROL,1 ;=Clear Condition Test Flag bit BTFSS CONTROL,7 ;=Check for new RX RETURN ;=No new RX -> leave subroutine GOTO COND_OK ;=Condition is true RETURN ;=Return to parent routine COND_OK BSF CONTROL,1 ;=Set Condition Test Flag bit BCF CONTROL,7 ;=Clear new RX Flag bit RETURN ;=Return to parent routine ; ; BFSMOUT ******* Slave Bus FSM actions ******* ; ; When reaching state 5, the broadcast and command received flags must be reset ; When reaching state 6 the slave command byte has to be stored in the TEMP_COM register ; When reaching state 7, ; the slave data byte has to be stored in the TEMP_DAT register ; the received command byte has to be checked against the slave ID ; the state has to evolve spontaneously to state 8 ; OUT_05 ; State 5 actions ; BCF CONTROL,3 ;=Clear Broadcast Received Flag bit. BCF CONTROL,2 ;=Clear New Command Received Flag bit GOTO INTER_END OUT_06 ; State 6 actions ; MOVF RX_BUF,0 ;=Place RX_BUF register content in W register MOVWF TEMP_COM ;=Store W register in TEMP_COM register GOTO INTER_END OUT_07 ; State 7 actions ; MOVF RX_BUF,0 ;= Place RX_BUF register content in W register MOVWF TEMP_DAT ;= Store W register in TEMP_DAT register INCF BFSM,1 ;= Increment BFSM to state 08 (spontaneous transition) ; ; ; Check the destination of the received command ; MOVLW 0xf0 ;= Prepare mask to get only 4 msb's of command ANDWF TEMP_COM,0 ;= destination address now in W SUBLW 0xf0 ;= check for broadcast address f BTFSC STATUS,2 GOTO OUT_07_BRD ;= Yes, it was a broadcast XORLW 0xf0 ;= Restore destination address in W SUBWF ID,0 ;= Are destination address and local ID equal ? BTFSC STATUS,2 GOTO OUT_07_LOC ;= Yes, this command was for here GOTO INTER_END ;= No, nothing to do with this command OUT_07_BRD BSF CONTROL,3 ;= Set Broadcast Received Flag bit. OUT_07_LOC BSF CONTROL,2 ;= Set New Command Received Flag bit MOVF TEMP_COM,0 ;= Place TEMP_COM register content in W register MOVWF RX_COM ;= Store W register in RX_COM register MOVF TEMP_DAT,0 ;= Place TEMP_DAT register content in W register MOVWF RX_DAT ;= Store W register in RX_DAT register GOTO INTER_END ;= ; ; ********* End of the BusMaster Finite State Machine ******** ; CCP_INT ; Process interrupt from RC2 50 Hz input. BCF PIR1,2 ;= Reset CCP interrupt flag ; TST MOVF PDELAY,W ;= Put 256 complement of firing delay SUBLW 0x00 ;= in W (firing delay in multiples of 51 microseconds) MOVWF TMR0 ;= and load it in TMR0 BCF INTCON,2 ;= Clear TMR0 Overflow Interrupt Flag bit BSF INTCON,5 ;= Enable TMR0 Overflow interrupt GOTO INTER_END ;= and terminate interrupt handling ; TMR0_INT ; Timer 0 interrupt handler BCF INTCON,2 ;= Clear TMR0 Overflow Interrupt Flag bit GOTO PCFSM ;= Enter the pump control finite state machine ; PFSM_1 ; process tmr0 interrupt when pump state = 1 (first delay = variable) ; ; The triac is fired, the optical command remains on for some microseconds ; The tmr0 is restarted to generate a new interrupt after 10 mS ; BSF PORTA,1 ; Fire the triac MOVLW 0x3D ; Prepare for a 10 mS delay before firing again the triac MOVWF TMR0 ; Load 256 - 195 = 61 in TMR0 BSF INTCON,5 ; Confirm enabling of TMR0 interrupt INCF PFSM,F ; set pump state 2 NOP ; Some delay for obtaining an adequate pulse width NOP NOP NOP NOP NOP NOP NOP GOTO INTER_END ; and finish interrupt handling ; PFSM_2 ; process tmr0 interrupt when pump state = 2 (second delay = 10 ms) ; ; The triac is fired, the optical command remains on for some microseconds ; Timer 0 is disabled until a new 50Hz sync signal arrives ; BSF PORTA,1 ; Fire the triac DECF PFSM,F ; Reset pump state to 1 BCF INTCON,5 ; Disable timer 0 interrupt BCF PIR1,2 ; Reset CCP interrupt flag BSF STATUS,5 ; Switch to bank 1 BSF PIE1,2 ; Enable interrupt from RC2 BCF STATUS,5 ; Switch back to bank 0 NOP ; Some delay for obtaining an adequate pulse width NOP NOP NOP NOP NOP GOTO INTER_END ; and finish interrupt handling; ; END