TITLE "Busmaster1" LIST p=16F870,n=0 __CONFIG 0x0C02 ; Busmaster Version 1.1. ; Busmaster Version 1.2. : New pin assignements for LED control ;BANK 0 ;------ ;PIC SPECIAL FUNCTION REGISTERS 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 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 ;CONTEXT AND BFSM REGISTERS W_TEMP EQU 0x20 ;W register buffer STAT_TEMP EQU 0x21 ;STATUS reg buffer PCLH_TEMP EQU 0x22 ;PCLATH reg buffer BFSM EQU 0x23 ;Bus Finite State Machine register DFSM EQU 0x24 ;Display Finite State Machine register TEMP EQU 0x25 ;General Purpose Temporary register (ie. testing of ID) ;MASTER MODULE REGISTERS RX_BUF EQU 0x70 ;Buffer for received data RX_COM EQU 0x71 ;Command register RX_DAT EQU 0x72 ;Data register TX EQU 0x73 ;Transmit register DISP_0 EQU 0x74 ;Display 0 register DISP_1 EQU 0x75 ;Display 1 register DTIME_0 EQU 0x76 ;Delay counter for display 0 DTIME_1 EQU 0x77 ;Delay counter for display 1 DTIME_OFF EQU 0x78 ;Delay counter for display off ID EQU 0x79 ;4 bit address of module (stored in 4 MSB's) CONTROL EQU 0x7A ;D7: NEW RX ;D6: NEW TX ;D5: NEW PACKAGE RECEIVED ;D2: NEW COMMAND + DATA RECEIVED ;D1: Condition Test Flag bit ;D0: TMR0 Overflow Flag bit TEMP_COM EQU 0x7B ;Temporary command register TEMP_DAT EQU 0x7C ;Temporary data register ;SYNCHRONIZATION SYMBOLS SYNC_M EQU 0x0A ;Change direction / Synchronize slaves SYNC_S EQU 0x0D ;Synchronize slaves ;Display delays DDELAY_0 EQU 0x10 DDELAY_1 EQU 0x10 DDELAY_OFF EQU 0x20 ;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 ORG 0x00 ; GOTO START ; ORG 0x04 ; GOTO INTER ; START ;OPTION REGISTER INITIALIZATION BSF STATUS,5 ;Switch to BANK1 BCF OPTION_REG,7 ;Enable 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 BCF OPTION_REG,2 ;\ BCF OPTION_REG,1 ;|Configure prescaler as 1:4 BSF OPTION_REG,0 ;/ BCF STATUS,5 ;Switch to BANK0 ;INTCON REGISTER INITIALIZATION BCF INTCON,7 ;Disable all interrupts BSF INTCON,6 ;Enable all peripheral interrupts BSF INTCON,5 ;Enable 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 ;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 0x00 ;00000000 in W-REG MOVWF TRISA ;All outputs PORTA MOVLW 0x00 ;00000000 in W-REG MOVWF TRISB ;All outputs PORTB MOVLW 0x80 ;10000000 in W-REG MOVWF TRISC ;RC7 is input MOVLW 0x06 ;00000110 in W-REG MOVWF ADCON1 ;All digital IO, Busmaster doesn't require any analog inputs. BCF STATUS,5 ;Switch to BANK0 ;TXSTA REGISTER INITIALIZATION BSF STATUS,5 ;Switch to BANK1 BCF TXSTA,7 ;Asynchronous mode BCF TXSTA,6 ;8 bit mode BCF TXSTA,5 ;Transmit disabled 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 BSF PORTC,0 ;Bus direction starts in send mode ('1') BSF PORTA,0 ;Bus direction led starts in send mode ('1') ;FSM & CONTROL REGISTER INITIALIZATION CLRF BFSM ;Clear the BFSM register (Bus State 0) CLRF DFSM ;Clear the DFSM register (Display state 0) CLRF CONTROL ;Clear the Control register ;ID REGISTER INITIALIZATION CLRF ID ;Set ID register to 00000000 (Master address is 0000) ;DISPLAY REGISTER INITIALIZATION BSF PORTC,4 ;Turn all displays off BSF PORTC,5 ; BSF INTCON,7 ;Enable Global Interrupts ; Main program loop. The program spends most of its time here ; MAIN NOP GOTO MAIN ; ; Interrupt handler (interrupts are now disabled) ; 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,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 ; 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 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 (Should never occur in busmaster !!!) ; MOVF RCREG,0 ;Empty Fifo MOVF RCREG,0 ;Empty Fifo MOVF RCREG,0 ;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,0 ;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,0 ;Place received byte in W register MOVWF RX_BUF ;Store received byte in RX_BUF register BSF CONTROL,7 ;reactivate USART receiver ; ; ********* Busmaster Finite State Machine ****************************************************** ; ; Find present state and perform any needed transitions ; ; Start search with states 9 and 7 for improving bus turn-around speed ; State 8 is a transient state, evolving spontaneously to state 9 ; BSTATE_09 ;Wait state - slave answers allowed in this state MOVLW 0x09 ;Check if BFSM = 9 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO BSTATE_07 ; No, try state 7 ; ; State 9 processing ; CALL CONDIT_00 ;Sync-M received ? BTFSC CONTROL,1 ; CALL SETBFSM_05 ;Yes, Jump to SETBFSM_05 routine (for setting BFSM register to state 5) GOTO BFSMOUT ;Perform actions required in present state BSTATE_07 ;Slave data state MOVLW 0x07 ;Check if BFSM = 7 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO BSTATE_00 ; No, try state 0 ; ; State 7 processing ; CALL CONDIT_04 ;Any byte (data byte) received ? BTFSC CONTROL,1 ; INCF BFSM,1 ;Yes, set state 8 (transient state) GOTO BFSMOUT ;Perform actions required in present state BSTATE_00 ;Idle State MOVLW 0x00 ;Check if BFSM = 0 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO BSTATE_01 ; No, try state 1 CALL CONDIT_00 ;Sync-M received ? BTFSC CONTROL,1 ; INCF BFSM,1 ;Yes, Increment BFSM register to state 01 GOTO BFSMOUT ;Perform actions required in present state BSTATE_01 ;Initialisation step 1. MOVLW 0x01 ;Check if BFSM = 1 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO BSTATE_02 ; No, try state 2 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 ;Initialisation step 2. MOVLW 0x02 ;Check if BFSM = 2 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO BSTATE_03 ; No, try state 3 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 ;Master Initialisation step 3. MOVLW 0x03 ;Check if BFSM = 3 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO BSTATE_04 ; No, try state 4 CALL CONDIT_01 ;Sync-S received ? BTFSC CONTROL,1 ; INCF BFSM,1 ;Yes,Increment BFSM register to state 04 CALL CONDIT_03 ;Anything different from Sync-S received ? BTFSC CONTROL,1 ; CLRF BFSM ;Yes, Reset BFSM register to state 0 GOTO BFSMOUT ;Perform actions required in present state BSTATE_04 ;Last state of master initialisation MOVLW 0x04 ;Check if BFSM = 4 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO BSTATE_05 ; No, try state 5 CALL CONDIT_00 ;Sync-M received ? BTFSC CONTROL,1 ; INCF BFSM,1 ;Yes, Increment BFSM register to state 5 CALL CONDIT_01 ;No, Sync-S received ? BTFSC CONTROL,1 ; GOTO BFSMOUT ;Yes, stay in state 4 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_05 ;Slave synchronization state MOVLW 0x05 ;Check if BFSM = 5 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO BSTATE_06 ; No, try state 6 CALL CONDIT_01 ;Sync-S received ? BTFSC CONTROL,1 ; INCF BFSM,1 ;Increment BFSM register to state 06 GOTO BFSMOUT ;Perform actions required in present state BSTATE_06 ;Slave command state MOVLW 0x06 ;Check if BFSM = 6 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO START ; FSM is in none of the defined states - Restart everything CALL CONDIT_03 ;Anything different from Sync-S received ? BTFSC CONTROL,1 ; INCF BFSM,1 ;Yes,Increment BFSM register to state 07 CALL CONDIT_01 ;Sync-S received ? BTFSC CONTROL,1 ; CALL SETBFSM_03 ;Yes, call SETBFSM_03 routine (for setting BFSM register to state 3) GOTO BFSMOUT ;Perform actions required in present state SETBFSM_03 MOVLW 0x03 ;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 ; ; ******* Bus master FSM actions ******* ; ; When reaching state 5 the bus has to be set in the downstream direction ; When reaching state 7 the slave command byte has to be stored in the TEMP_COM register ; When reaching state 8, ; the bus has to be set in the upstream direction ; the slave data byte has to be stored in the TEMP_DAT register ; the state has to evolve spontaneously to state 9 ; ; States 5 and 8 are handled first for optimization of bus reversal ; BFSMOUT MOVLW 0x05 ;Check if BFSM = 5 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO OUT_08 ; No, try state 8 ; ; State 5 actions ; BSF PORTC,0 ;Set busdirection downstream BSF PORTA,0 ;Enable downstream led GOTO INTER_END OUT_08 MOVLW 0x08 ;Check if BFSM = 8 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO OUT_07 ; No, try state 7 ; ; State 8 actions ; BCF PORTC,0 ;Set busdirection upstream BCF PORTA,0 ;Enable upstream led 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 09 GOTO INTER_END OUT_07 MOVLW 0x07 ;Check if BFSM = 7 SUBWF BFSM,0 ; BTFSS STATUS,2 ; GOTO INTER_END ; No, no actions to be performed this time. ; ; State 7 actions ; BSF PORTC,0 ;Set busdirection downstream BSF PORTA,0 ;Enable downstream led 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 ; ; ********* End of the BusMaster Finite State Machine ******** ; ; ********* Display Timer interrupt handler ********* ; TMR0_INT BCF INTCON,2 ;Clear TMR0 Overflow Interrupt Flag bit MOVF TEMP_COM,0 ;Display most recently received command byte MOVWF DISP_0 MOVF TEMP_DAT,0 ;Display most recently received data byte MOVWF DISP_1 ; ; ********* Display Finite State Machine ******** ; DSTATE_00 ;Switch on display 0 MOVLW 0x00 ;Check if DFSM = 0 SUBWF DFSM,0 ; BTFSS STATUS,2 ; GOTO DSTATE_01 ; No, try state 1 ; ; Process state 0 of the display ; MOVLW DDELAY_0 ;Initialise On delay for display 0 MOVWF DTIME_0 MOVF DISP_0,0 ;Place DISP_0 register in W register MOVWF PORTB ;Place W register on PORTB BCF PORTC,4 ;Switch on display 0. INCF DFSM,1 ;Increment DFSM register to state 01 GOTO INTER_END ;Perform actions required in present state DSTATE_01 ;Display 0 stays on until DTIME_0 reaches 0. MOVLW 0x01 ;Check if DFSM = 1 SUBWF DFSM,0 ; BTFSS STATUS,2 ; GOTO DSTATE_02 ; No, try state 2 ; ; Process state 1 of the display ; DECFSZ DTIME_0,1 ;Time over ? GOTO INTER_END ; Not yet, stay in state 1, and finish display handling INCF DFSM,1 ; Yes, Increment DFSM to state 2 GOTO INTER_END ;Finish display handling DSTATE_02 ;Switch on display 1 MOVLW 0x02 ;Check if DFSM = 2 SUBWF DFSM,0 ; BTFSS STATUS,2 ; GOTO DSTATE_03 ; No, try state 3 ; ; Process state 2 of the display ; MOVLW DDELAY_1 ;Initialise On delay for display 1 MOVWF DTIME_1 BSF PORTC,4 ;Switch off display 0. MOVF DISP_1,0 ;Place DISP_0 register in W register MOVWF PORTB ;Place W register on PORTB BCF PORTC,5 ;Switch on display 1. INCF DFSM,1 ;Increment DFSM register to state 03 GOTO INTER_END ;Finish display handling DSTATE_03 ;Display 1 stays on until DTIME_1 reaches 0. MOVLW 0x03 ;Check if DFSM = 3 SUBWF DFSM,0 ; BTFSS STATUS,2 ; GOTO DSTATE_04 ; No, try state 4 ; ; Process state 3 of the display ; DECFSZ DTIME_1,1 ;Time over ? GOTO INTER_END ; Not yet, stay in state 3, and finish display handling INCF DFSM,1 ; Yes, Increment DFSM to state 2 GOTO INTER_END ;Finish display handling DSTATE_04 ;Switch off all displays MOVLW 0x04 ;Check if DFSM = 4 SUBWF DFSM,0 ; BTFSS STATUS,2 ; GOTO DSTATE_05 ; No, try state 5 ; ; Process state 4 of the display ; MOVLW DDELAY_OFF MOVWF DTIME_OFF BSF PORTC,5 ;Switch off display 1. INCF DFSM,1 ;Increment DFSM register to state 05 GOTO INTER_END ;Perform actions required in present state DSTATE_05 ;All displays stay off until DTIME_OFF reaches 0. MOVLW 0x05 ;Check if DFSM = 5 SUBWF DFSM,0 ; BTFSS STATUS,2 ; GOTO START ; No, Display FSM error, restart everything. ; ; Process state 5 of the display ; DECFSZ DTIME_OFF,1 ;Time over ? GOTO INTER_END ; Not yet, stay in state 5, and finish display handling CLRF DFSM ; Yes, Reset DFSM to state 0 GOTO INTER_END ;Finish display handling END