;---------------------------------------------------------------------------- ;protocol.h ;PICBench SCADA Protocol Driver ;Copyright Andrew Ferry 2004 ;---------------------------------------------------------------------------- ;This implements PICBench Comms Protocol Driver Macros ;---------------------------------------------------------------------------- ;Format: address cmd data1 data2 end ;address must have bit9 set ;EPROM ADDRESS 0x00 must be set to the address ID you want the device to ;respond to CBLOCK PROT_RX_STATE PROT_TX_STATE RX_BUF PROT_ADDRESS PROT_COMMAND PROT_DATA1 PROT_DATA2 PROT_CHECKSUM ENDC ; these are bits ADDR equ 1 CMD equ 2 DAT1 equ 3 DAT2 equ 4 CHKSUM equ 5 ;so are these READ equ 1 WRITE equ 2 SCADA_INIT MACRO ;get address from eeprom IFDEF __16F876 bsf STATUS,RP1 ;BANK 2 movlw 0x00 ;eprom source address movwf EEADR bsf STATUS,RP0 ;BANK 3 bcf EECON1,7 ;eeprom not flash bsf EECON1,RD ;read bcf STATUS,RP0 ;BANK 2 movf EEDATA,W bcf STATUS,RP1 ;BANK 0 ENDIF IFDEF __16F627 bsf STATUS,RP0 ;BANK 1 movlw 0x00 ;eprom source address movwf EEADR bsf EECON1,RD ;read movf EEDATA,W bcf STATUS,RP0 ;BANK 0 ENDIF movwf PROT_ADDRESS COMMS_INIT ENDM SCADA_RX MACRO local rxaddr,rxdata local rxover,rxframe local rxresp,rxnext,rxreset,rxend local rxaddmatch,rxcmd,rxcmdr,rxcmdw local rxdata1,rxdata2 local datach1r,datach1w,datach2r,datach2w local rxchksum,rxdocmd btfsc RSTA,OERR ;if overrun error occurred goto rxover ;then go handle error btfsc RSTA,FERR ;if framing error occurred goto rxframe ;then go handle error btfsc RSTA,RX9D ;skip if clear goto rxaddr goto rxdata rxover: bcf RSTA,CREN ;reset the receiver logic bsf RSTA,CREN ;enable reception again goto rxreset ;reset protocol rxframe: movf RREG,W ;discard received data that has error goto rxreset ;reset protocol rxaddr: movf RREG,W ;store received char movwf RX_BUF movwf PROT_CHECKSUM ;start new checksum movf PROT_ADDRESS,W ;if address matches goto addok subwf RX_BUF,W btfsc STATUS,Z goto rxaddmatch goto rxreset ;wait for next address byte rxaddmatch: clrf PROT_RX_STATE ;reset data state machine clrf PROT_COMMAND ;reset receive data clrf PROT_DATA1 clrf PROT_DATA2 bsf PROT_RX_STATE,CMD bcf RSTA,ADDEN ;switch to receive all goto rxend ;wait for CMD rxdata: movf RREG,W ;store received char movwf RX_BUF btfsc PROT_RX_STATE,CHKSUM goto rxchksum addwf PROT_CHECKSUM,F ;update checksum btfsc PROT_RX_STATE,CMD goto rxcmd btfsc PROT_RX_STATE,DAT1 goto rxdata1 btfsc PROT_RX_STATE,DAT2 goto rxdata2 ;if none of the above reset protocol goto rxreset rxcmd: movlw "R" subwf RX_BUF,W btfsc STATUS,Z ;do next if cmd is R goto rxcmdr movlw "W" subwf RX_BUF,W btfsc STATUS,Z ;do next if cmd is W goto rxcmdw goto rxreset rxcmdr: bsf PROT_COMMAND,READ goto rxnext rxcmdw: bsf PROT_COMMAND,WRITE goto rxnext rxdata1: movf RX_BUF,W btfsc PROT_COMMAND,READ goto datach1r btfsc PROT_COMMAND,WRITE goto datach1w ;defer goto rxreset datach1r: ;read from first address movwf FSR movf INDF,W movwf PROT_DATA1 datach1w: ;defer movwf PROT_DATA1 goto rxnext rxdata2: movf RX_BUF,W btfsc PROT_COMMAND,READ goto datach2r btfsc PROT_COMMAND,WRITE goto datach2w ;defer goto rxreset datach2r: ;this is the second address to read movwf FSR movf INDF,W movwf PROT_DATA2 goto rxnext datach2w: ;defer movwf PROT_DATA2 goto rxnext rxchksum: movf PROT_CHECKSUM,W ;if checksum matches goto next state subwf RX_BUF,W btfsc STATUS,Z goto rxdocmd goto rxreset ;reset & start again rxdocmd: btfss PROT_COMMAND,WRITE goto rxresp movf PROT_DATA1,W ;a write is needed movwf FSR movf PROT_DATA2,W movwf INDF movf INDF,W movwf PROT_DATA2 ;return data written in 2nd byte rxresp: ;send the response clrf PROT_TX_STATE bsf PROT_TX_STATE,ADDR TX_START ;reset the rx state & wait for a new command goto rxreset rxnext: bcf STATUS,C rlf PROT_RX_STATE,F goto rxend rxreset: bsf RSTA,ADDEN ;receive only address bytes clrf PROT_RX_STATE ;reset data state machine goto rxend rxend: ENDM SCADA_TX MACRO local txaddr,txcmd,txdata1,txdata2,txeof,txnext,txend btfsc PROT_TX_STATE,ADDR goto txaddr btfsc PROT_TX_STATE,CMD goto txcmd btfsc PROT_TX_STATE,DAT1 goto txdata1 btfsc PROT_TX_STATE,DAT2 goto txdata2 btfsc PROT_TX_STATE,CHKSUM goto txeof goto txend txaddr: movlw 0 ;master address 0 movwf TREG movwf PROT_CHECKSUM ;start new checksum goto txnext txcmd: movlw '*' ;response command movwf TREG addwf PROT_CHECKSUM,F ;update checksum goto txnext txdata1: movf PROT_DATA1,W movwf TREG addwf PROT_CHECKSUM,F ;update checksum goto txnext txdata2 movf PROT_DATA2,W movwf TREG addwf PROT_CHECKSUM,F ;update checksum goto txnext txeof: movf PROT_CHECKSUM,W movwf TREG TX_STOP goto txnext txnext: bcf STATUS,C rlf PROT_TX_STATE,F txend: ENDM