;****************************************************************** ;* * ;* Filename: th_12f675.asm ;* * ;****************************************************************** list p=12f675 ; list directive to define processor #include ; errorlevel -302 __CONFIG _BODEN_ON & _MCLRE_OFF & _PWRTE_ON & _WDT_ON & _HS_OSC #define MYADD 0x01 ; Address of the device #define SRVADD 0x0 #define STX 0x02 #define ETX 0x03 #define TIMEOUT .45 HFLEN equ .11 RSLEN equ .23 RSCMD equ .2 ; offset of first data byte in RX frame ; ; file register variables ; cblock 0x20 ;0x20-0x5f banks 0 ; ; file locations used by ISR for saving and restoring the stack ; W_ISR ; ISR 'W' S_ISR ; ISR 'STATUS' ; ; file variables ; PROC_1 ; PROC_2 ; PROC_3 ; RT_REG RT_BIT ; TX-232 bit count RT_VAR ; TX-232 data byte RT_TIC ; TX-232 tics counter RR_REG RR_BIT ; RX-232 bit count RR_TIC ; RX-232 tics counter RR_VAR ; RX-232 data byte HF_TIC ; HF tic count HF_LEN ; length of the data bit received HF_CNT ; HF bit count HF_VAR ; HF data byte HF_POS ; HF buffer index TX_IN ; TX buffer in pointer TX_OUT ; TX buffer out pointer SEQNCE ; sequence number CHKSUM ; checksum ; ; buffers ; HFBUF:HFLEN ; HF buffer TXBUF:RSLEN ; RX RS232 buffer RR_ADD ; address of received frame RR_SLN ; sequence/len of frame RR_CMD ; command of the frame RR_PAY ; payload of received frame RR_CNT ; length of frame RR_CHK ; checksum of received frame TEMP1 ; temporary var1 COUNT ; temporary counter endc ; ; PROC_1 flag bits ; RR_INP equ 0x00 ; RS232 input RR_SRT equ 0x01 ; RS232 start RR_OK equ 0x02 ; character available RR_OUP equ 0x03 ; RS232 output RR_PRG equ 0x04 ; 1=rx in progress HF_INP equ 0x05 ; Received bit IT_TIC equ 0x06 ; interrupt done HF_CHK equ 0x07 ; HF mode to be checked ; ; PROC_2 flag bits ; HF_CHG equ 0x00 ; 1=HF data has changed FR_PRG equ 0x01 ; 1=RX frame in progress FR_ADD equ 0x02 ; 1=frame address received FR_SLN equ 0x03 ; 1=frame SLN received FR_CMD equ 0x04 ; 1=cmd received FR_FWD equ 0x05 ; 1=forward frame TR_PRG equ 0x06 ; 1=tx in progress TR_AVL equ 0x07 ; 0=buffer empty ; ; PROC_3 flag bits ; HF_PRG equ 0x00 ; 1=HF frame in progress TX_SND equ 0x01 ; 1=TX frame ready to send TR_STR equ 0x02 ; 1=character to send HF_DLT equ 0x03 ; 1=HF input change HF_DIN equ 0x04 ; Received data HF_TOU equ 0x05 ; 1=HF data time-out HF_MOD equ 0x06 ; 0=TX 1=WS WS_SND equ 0x07 ; 1=WS frame ready to send ; ; I/O ports ; GP4 and GP5 reserved for Xtal oscillator ; HFPIN equ 0x00 ; (GP0) HF RTPIN equ 0x01 ; (GP1) RS-232 TX TSTP1 equ 0x02 ; (GP2) LED RRPIN equ 0x03 ; (GP3) RS-232 RX ; ; I/O definition ; #define HF_IN GPIO,HFPIN ; Receiver input #define RS_IN GPIO,RRPIN ; RS232 input #define RS_OUT GPIO,RTPIN ; RS232 output #define LED GPIO,TSTP1 ; LED output ; ; RS232 receive flags ; #define FRR_INP PROC_1,RR_INP ; RS232 input #define FRR_SRT PROC_1,RR_SRT ; RS232 start #define FRR_OK PROC_1,RR_OK ; character available #define FRR_OUP PROC_1,RR_OUP ; RS232 output #define FRR_PRG PROC_1,RR_PRG ; 1=rx in progress ; ; RS232 transmit flags ; #define FTR_PRG PROC_2,TR_PRG ; 1=tx in progress #define FTR_AVL PROC_2,TR_AVL ; 0=buffer empty #define FTR_SRT PROC_3,TR_STR ; 1=character to send ; ; HF receive flags ; #define FHF_INP PROC_1,HF_INP ; Received bit #define FHF_CHG PROC_2,HF_CHG ; 1=HF data has changed #define FHF_PRG PROC_3,HF_PRG ; 1=HF frame in progress #define FTX_SND PROC_3,TX_SND ; 1=TX frame ready to send #define FHF_DLT PROC_3,HF_DLT ; 1=HF input change #define FHF_DIN PROC_3,HF_DIN ; Received data value #define FHF_TOU PROC_3,HF_TOU ; 1=HF data time-out #define FHF_MOD PROC_3,HF_MOD ; 0=TX 1=WS #define FWS_SND PROC_3,WS_SND ; 1=WS frame ready to send #define FHF_CHK PROC_1,HF_CHK ; HF mode to be checked ; ; Interrupt flags ; #define FIT_TIC PROC_1,IT_TIC ; interrupt done ; ; RS232 frame flags ; #define FFR_PRG PROC_2,FR_PRG ; 1=RX frame in progress #define FFR_ADD PROC_2,FR_ADD ; 1=frame address received #define FFR_SLN PROC_2,FR_SLN ; 1=frame SLN received #define FFR_CMD PROC_2,FR_CMD ; 1=cmd received #define FFR_FWD PROC_2,FR_FWD ; 1=forward frame ;****************************************************************** ;* * ;* * ;* Start... * ;* * ;* * ;****************************************************************** org 0x0000 START clrf PCLATH clrf STATUS ; |B0 goto MAIN ; |B0 org 0x0004 ; ; interrupt routine ; ISR ; ; save context ; 4 steps ; movwf W_ISR ; save W-reg |B? swapf STATUS,W ; doesn't change STATUS bits |B? movwf S_ISR ; save STATUS reg |B? ; ; Real time actions ; ; ; process RS232 output ; 6 steps ; btfsc FRR_OUP goto RR_OU_1 nop RR_OU_0 bcf RS_OUT ; output RS232 = 0 goto RR_OU_F RR_OU_1 bsf RS_OUT ; output RS232 = 1 goto RR_OU_F RR_OU_F ; ; process RS232 input ; 9 steps ; ; Check RS232 input bcf FRR_SRT ; clear start flag btfsc RS_IN goto RR_IN_1 RR_IN_0 ; RS232 input is 0 btfss FRR_INP goto RR_IN_D bsf FRR_SRT ; 1->0 = possible start RR_IN_D bcf FRR_INP ; input RS232 = 0 goto RR_IN_F RR_IN_1 ; RS232 input is 1 bsf FRR_INP ; input RS232 = 1 nop nop goto RR_IN_F RR_IN_F ; ; process HF input ; 9 steps ; bcf FHF_DLT btfsc HF_IN goto HF_IN_1 nop HF_IN_0 btfsc FHF_DIN bsf FHF_DLT ; RX input changed bcf FHF_DIN ; RX input = 0 goto HF_IN_F HF_IN_1 btfss FHF_DIN bsf FHF_DLT ; RX input changed bsf FHF_DIN ; RX input = 1 goto HF_IN_F HF_IN_F ; ; process TICs ; 1 steps bsf FIT_TIC ; TIC request ; ; data processing ; ;****************************************************************** ; ; RX232C - Process RS232 character receiving ; RX232C btfsc FRR_PRG goto RX232C1 btfss FRR_SRT ; up front ? goto TX232C ; start bit movlw .2 movwf RR_TIC ; two ticks movlw .10 movwf RR_BIT ; 10 bits bsf FRR_PRG ; rx in progress goto RX232CE RX232C1 decfsz RR_TIC,F ; RX character is in progress goto RX232CE ; tics = 0 movlw .4 movwf RR_TIC decfsz RR_BIT,F goto RX232C2 ; last bit received bcf FRR_PRG bsf FRR_OK goto RX232CE RX232C2 bsf STATUS,C btfss FRR_INP bcf STATUS,C rrf RR_VAR,F RX232CE bcf FRR_SRT ; clear up front ? ;****************************************************************** ; ; TX232C - Process RS232 character sending ; TX232C btfsc FTR_PRG goto TX232C1 btfss FTR_SRT ; character in TR_VAR ? goto TXEND movfw RT_VAR ; character requested in TR_VAR movwf RT_REG movlw .10 movwf RT_BIT ; set TX bit count |B0 bcf FTR_SRT ; initiate TX |B0 bsf FTR_PRG bcf STATUS,C ; start bit goto TXBIT TX232C1 btfss FTR_PRG goto TXEND decfsz RT_TIC,f goto TXEND decfsz RT_BIT,f ; next bit... goto TXBITN bcf FTR_PRG ; End of character transmission goto TXEND TXBITN bsf STATUS,C ; fills with 1 (stop) rrf RT_REG,f TXBIT ; send the bit in carry bcf FRR_OUP btfsc STATUS,C bsf FRR_OUP movlw .4 ; 4 tics - 4800Bds movwf RT_TIC goto TXEND ; TX buffer is empty bcf FTR_AVL ; buffer empty ; goto TXEND TXEND ;****************************************************************** ; ; HFINCC - Process HF receiver input ; btfsc FHF_DLT goto HFCHG HFINCC movlw TIMEOUT+1 ; timeout occured ? xorwf HF_TIC,W btfsc STATUS,Z ; HF reaches max 45 tics ? goto HFEND incf HF_TIC,F ; tic = 57uS movlw TIMEOUT ; timeout = 2.5ms xorwf HF_TIC,W btfss STATUS,Z ; HF reaches max 45 tics ? goto HFEND bsf FHF_INP ; set input data btfss FHF_DIN bcf FHF_INP movfw HF_TIC movwf HF_LEN bsf FHF_CHG bsf FHF_TOU ; set time-out flag goto HFEND HFCHG bsf FHF_INP ; set input data btfsc FHF_DIN bcf FHF_INP HFNCHG bsf FHF_CHG ; HF input has changed (or timeout) movfw HF_TIC movwf HF_LEN clrf HF_TIC goto HFEND HFEND ; ; restore context ; 7 steps ; ISR_XIT bcf INTCON,T0IF ; clear TMR0 irq flag |B0 swapf S_ISR,W ; |B0 movwf STATUS ; restore STATUS |B? swapf W_ISR,f ; don't screw up STATUS |B? swapf W_ISR,W ; restore W-reg |B? retfie ; return from interrupt |B? ; ;****************************************************************** ;****************************************************************** ; ; Initialization ; MAIN clrf GPIO ; init GPIO bcf RS_OUT ; TX=0 movlw b'00000111' ; |B0 movwf CMCON ; digital I/O |B0 bsf STATUS,RP0 ; bank 1 |B1 ; timer 0 configuration, prescaler to WDT, no pull-ups movlw b'10001111' ; timer0 on internal clock, |B1 movwf OPTION_REG ; and pull-ups -> option register clrf VRCON ; disable Voltage Reference |B1 movlw B'00000000' ; Configure analog |B1 movwf ANSEL ; inputs |B1 movlw b'11111001' ; GP0,GP3=IN GP1,GP2=OUT |B1 movwf TRISIO ; Set PortA I/O for intput/output |B1 clrf PIE1 ; clear peripheral irq flags |B1 bcf STATUS,RP0 ; select bank 0 |B0 movlw b'00000000' ; A/D disabled movwf ADCON0 ; bcf STATUS,RP0 ; bank 0 |B0 ; clear RS-232 flags before turning on interrupts clrf PROC_1 ; clear process latch variable |B0 clrf PROC_2 ; clear process latch variable |B0 clrf PROC_3 ; clear process latch variable |B0 bsf FRR_OUP ; output RS232=1 (stop condition) bsf RS_OUT ; output RS232=1 (stop condition) ;****************************************************************** bsf LED ; LED ON |B0 call DEL100 ; delay 100ms bcf LED ; LED OFF |B0 call DEL100 ; delay 100ms bsf LED ; LED ON |B0 call DEL100 ; delay 100ms bcf LED ; LED OFF |B0 call DEL100 ; delay 100ms bsf LED ; LED ON |B0 call DEL100 ; delay 100ms bcf LED ; LED OFF |B0 call DEL100 ; delay 100ms bsf LED ; LED ON |B0 call DEL100 ; delay 100ms bcf LED ; LED OFF |B0 call DEL100 ; delay 100ms bsf LED ; LED ON |B0 call DEL100 ; delay 100ms bcf LED ; LED OFF |B0 call DEL100 ; delay 100ms clrf HF_POS clrf SEQNCE clrf HF_TIC movlw TXBUF movwf TX_IN movwf TX_OUT ; ; Allow interrupts ; bsf STATUS,RP0 ; select Bank 1 |B1 clrf PIE1 ; mask all peripheral irqs |B1 clrf IOC ; |B1 bcf STATUS,RP0 ; select Bank 0 |B0 clrf PIR1 ; clear peripheral irq flags |B0 clrf INTCON ; Clear flags |B0 bsf INTCON,T0IE ; allow TIMER0 interrupts |B0 bsf INTCON,GIE ; enable global irqs |B0 movlw 0x01 movwf RR_ADD call IDENT ;****************************************************************** ; ; Main loop ; ; LOOP clrwdt ; Clear watchdog |B0 ; processing routines call PROCESS btfsc FRR_OK goto RR_REC ; character received btfsc FFR_PRG ; if on-going rs232 frame goto LOOPE ; end of loop btfsc FTX_SND ; if no pending hf frame goto TX_REC ; hf frame received btfsc FWS_SND ; if no pending hf frame goto WS_REC ; hf frame received goto LOOPE ; end of loop ;****************************************************************** ; ; A TX-HF frame is received. process it... ; TX_REC call TX2BUF ; send the frame to RS232 bcf FTX_SND ; clear pending hf frame goto LOOPE ;****************************************************************** ; ; A WS-HF frame is received. process it... ; WS_REC call WS2BUF ; send the frame to RS232 bcf FWS_SND ; clear pending hf frame goto LOOPE ;****************************************************************** ; ; A character is received. Process it... ; RR_REC bcf FRR_OK ; clear RR flag btfsc FFR_PRG ; frame in progress ? goto PRCHAR ; wait for STX movlw STX xorwf RR_VAR,W btfss STATUS,Z goto LOOPE ; STX received, begin of frame bsf FFR_PRG clrf CHKSUM goto LOOPE PRCHAR ; process characters btfsc FFR_ADD goto PRCHAR1 ; process address movfw RR_VAR movwf RR_ADD bsf FFR_ADD goto LOOPE PRCHAR1 btfsc FFR_SLN goto PRCHAR2 ; process sequence/length movfw RR_VAR movwf RR_SLN ; compute the length of the rest including CRC andlw 0x0f addlw .2 ; adjust for end of frame movwf RR_CNT bsf FFR_SLN ; SLN received ; we have address and length. Need to decide ; process address movfw RR_ADD andlw 0x0f ; get addresses xorlw MYADD btfsc STATUS,Z goto LOOPE ; Not for me, forward the frame without any change movlw STX call TX232 movfw RR_ADD call TX232 movfw RR_SLN call TX232 bsf FFR_FWD goto LOOPE PRCHAR2 btfsc FFR_FWD goto PR_FWD btfsc FFR_CMD goto PRCHAR3 ; process command movfw RR_VAR movwf RR_CMD bsf FFR_CMD decf RR_CNT,F goto LOOPE PRCHAR3 ; store payload and checksum. ; Consider Payload is one byte long. movfw RR_CHK movwf RR_PAY movfw RR_VAR movwf RR_CHK decfsz RR_CNT,F goto LOOPE ; end of my frame movlw 1 xorwf RR_CMD,W btfss STATUS,Z goto PRCHAR4 ; ping request call PING goto PR_END PRCHAR4 movlw 2 xorwf RR_CMD,W btfss STATUS,Z goto PR_END ; ident request call IDENT goto PR_END PR_FWD ; forward the character until end of frame decfsz RR_CNT,F goto LOOP3 ; end of frame: send checksum movfw RR_VAR call TX232 ; close the frame PR_END bcf FFR_PRG bcf FFR_ADD bcf FFR_SLN bcf FFR_CMD bcf FFR_FWD goto LOOPE LOOP3 ; send character to TX queue movfw RR_VAR call TX232 LOOPE goto LOOP ;****************************************************************** ; ; for tests... ; testbuf movlw 'F' ;send a new character call TX232 movlw '6' ;send a new character call TX232 movlw 'F' ;send a new character call TX232 movlw 'B' ;send a new character call TX232 movlw 'B' ;send a new character call TX232 return; ;****************************************************************** ; ; processing routines ; PROCESS call HFC ;process HF reception call TX232S ;process character sending return ;****************************************************************** ; ; Answer to a ping request ; swap adresses, set seq number, copy the data and update checksum ; PING clrf CHKSUM movlw STX call TX232 swapf RR_ADD,W ;swap addresses to answer addwf CHKSUM,F call TX232 ; sequence number movlw 0x0f andwf RR_SLN,F ;clean seq number swapf SEQNCE,W iorwf RR_SLN,W ;add to length addwf CHKSUM,F call TX232 call INCSEQ movfw RR_CMD addwf CHKSUM,F call TX232 movfw RR_PAY addwf CHKSUM,F call TX232 negf CHKSUM,W call TX232 return ;****************************************************************** ; ; Answer to a ping request ; swap adresses, set seq number, copy the data and update checksum ; IDENT clrf CHKSUM movlw STX call TX232 swapf RR_ADD,W ;swap addresses to answer addwf CHKSUM,F call TX232 ; Length movlw 0x05 movwf RR_SLN ; sequence number swapf SEQNCE,W iorwf RR_SLN,W ;add to length addwf CHKSUM,F call TX232 call INCSEQ movlw 0x02 addwf CHKSUM,F call TX232 movlw 'R' addwf CHKSUM,F call TX232 movlw 'X' addwf CHKSUM,F call TX232 movlw ' ' addwf CHKSUM,F call TX232 movlw 'V' addwf CHKSUM,F call TX232 movlw '2' addwf CHKSUM,F call TX232 negf CHKSUM,W call TX232 return ;****************************************************************** ; ; Fill the RS-OUT buffer with the TX-HF frame ; TX2BUF clrf CHKSUM movlw STX call TX232 ; adresses movlw (MYADD*.16)+SRVADD ;from=1 to==0 addwf CHKSUM,F call TX232 ; sequence number swapf SEQNCE,W iorlw 0x05 ;sequence len=6 -> 5 addwf CHKSUM,F call TX232 call INCSEQ ;increment sequence number movf HFBUF,W addwf CHKSUM,F call TX232 movf HFBUF+1,W addwf CHKSUM,F call TX232 movf HFBUF+2,W addwf CHKSUM,F call TX232 movf HFBUF+3,W addwf CHKSUM,F call TX232 movf HFBUF+4,W addwf CHKSUM,F call TX232 movf HFBUF+5,W addwf CHKSUM,F call TX232 negf CHKSUM,W ;to have the SUM == 0 call TX232 return ;****************************************************************** ; ; Fill the RS-OUT buffer with the WS-HF frame ; WS2BUF clrf CHKSUM movlw STX call TX232 ; adresses movlw (MYADD*.16)+SRVADD ;from=1 to==0 addwf CHKSUM,F call TX232 ; sequence number decf HF_POS,F ; len = length - 1 swapf SEQNCE,W iorwf HF_POS,W ; add len addwf CHKSUM,F call TX232 call INCSEQ ; increment sequence number incf HF_POS,F ; adjust length clrf COUNT ; position index WS2BUF1 movlw HFBUF addwf COUNT,W movwf FSR movfw INDF addwf CHKSUM,F call TX232 incf COUNT,F decfsz HF_POS,F goto WS2BUF1 negf CHKSUM,W ;to have the SUM == 0 call TX232 return ; ;****************************************************************** ; ; TX232 - enter with character to be sent in W ; character will be put in TX ring buffer ; TX232 movwf TEMP1 movf TX_IN,W ; get pointer movwf FSR movf TEMP1,W movwf INDF ; write character ; increment in pointer incf TX_IN,F ; increment pointer movlw TXBUF+RSLEN ; end of buffer ? xorwf TX_IN,W btfss STATUS,Z return ; no movlw TXBUF ; yes movwf TX_IN ; beginning return ; ;****************************************************************** ; ; Check send buffer and put character in TX register if needed ; TX232S movfw TX_IN xorwf TX_OUT,w btfsc STATUS,Z return ; TX buffer empty ; check if room in register btfsc FTR_SRT return ; register not empty movfw TX_OUT ; get pointer movwf FSR movfw INDF movwf RT_VAR ; character val in register bsf FTR_SRT ; request character send ; increment out pointer incf TX_OUT,F ; increment pointer movlw TXBUF+RSLEN ; end of buffer ? xorwf TX_OUT,W btfss STATUS,Z return ; no movlw TXBUF ; yes movwf TX_OUT ; beginning return ;****************************************************************** ; ; HFC - processing of receiver data ; ; 1 tic = 52uS ; ; Format of the TX frames ; ======================= ; ; _____ ; | |____| bit 0 1200uS + 1000uS ; __ ; | |____| bit 1 500uS + 1000uS ; ; data = 1 : < 300uS = error ; < 800uS = bit1 ; < 1600uS = bit0 ; > 1600uS = error ; ; data = 0 : < 700uS = error ; < 1300uS = validate ; > 1300uS = error ; ; ; ; Format of the WS frames ; ======================= ; ; ; _____ ; | |__| bit 0 800uS + 400uS ; __ ; | |_____| bit 1 400uS + 800uS ; ; data = 1 < 300uS = error ; < 600uS = bit1 ; < 1000uS = bit0 ; > 1000uS = error ; ; data = 0 < 300uS = error ; < 600uS = bit0 (validate if data1 bit0) ; < 1000uS = bit1 (validate if data1 bit1) ; > 1000uS = error ; ; ; Type selection on first bit (2nd part, data = 0) ; ================================================ ; ; if data = 0 < 300 = error ; if data = 0 < 600 = WS ; if data = 0 < 1300 = TX ; if data = 0 > 1300 = error ; ; HFC btfss FHF_CHG goto HFC_END ; input changed btfsc FTX_SND goto HFC_END ; frame waiting ; input changed btfsc FWS_SND goto HFC_END ; frame waiting bcf FHF_CHG ; bit received btfsc FHF_CHK ; mode check ? goto HFC_CHK btfss FHF_PRG ; frame in progress ? goto HFC_1ST btfsc FHF_MOD ; yes -> process goto WS_DINX ; WS protocole goto HF_DINX ; TX protocole ; data = 1 -> begin of frame ? HFC_1ST btfss FHF_INP goto HFC_END ;****************************************************************** ; ; Decode 1st bit of frame data = 1 (always 0) ; ; data = 1 : begin of frame ; check length : 600uS < data1 < 1200uS movlw .12 ; 13 tics subwf HF_LEN,F btfss STATUS,C goto HFC_E1 ; < 625uS -> error movlw .18 ; 30 tics subwf HF_LEN,F btfsc STATUS,C goto HFC_E1 ; > 1560uS -> error clrf HF_POS ; begin of sequence movlw .8 movwf HF_CNT ; bit counter = 8 bsf FHF_PRG ; begin of frame bsf FHF_CHK ; validate mode check goto HFC_V0 ; 1st bit always 0 ;****************************************************************** ; ; Decode 1st bit of frame data = 0 (always 0) ; HFC_CHK bcf FHF_CHK ; end mode check bsf FHF_MOD ; WS mode by default ; check length : 300uS < ws < 600uS < tx < 1200uS movlw .5 ; 5 tics subwf HF_LEN,F btfss STATUS,C goto HFC_E1 ; < 260uS -> error movlw .7 ; 23 tics subwf HF_LEN,F btfss STATUS,C goto HFC_END ; < 650uS -> WS data length OK movlw .12 ; 24 tics subwf HF_LEN,F btfsc STATUS,C goto HFC_E1 ; > 1250uS -> error bcf FHF_MOD ; TX mode goto HFC_END ; data length OK ;****************************************************************** ; ; Decode TX type frames ; HF_DINX btfss FHF_INP ; frame in progress goto HFC_B0 goto HFC_B1 ; ; process data length ; HFC_B1 ; data = 1 / check length movlw .6 ; 6 tics subwf HF_LEN,F btfss STATUS,C goto HFC_E1 ; < 300uS -> error movlw .9 ; 15 tics subwf HF_LEN,F btfss STATUS,C goto HFC_V1 ; < 780uS movlw .15 ; 30 tics subwf HF_LEN,F btfss STATUS,C goto HFC_V0 ; < 1510uS HFC_E1 ; incorrect length goto HFC_ERR ; ; length of data1 < 780uS => bit=1 ; HFC_V1 bsf STATUS,C goto HFC_V ; ; length of data1 < 1510uS => bit=0 ; HFC_V0 bcf STATUS,C HFC_V rlf HF_VAR,f goto HFC_OK ; ; data = 0 / check length ; HFC_B0 btfsc FHF_TOU ; timeout ? goto HFC_1 movlw .13 ; 13 tics subwf HF_LEN,F btfss STATUS,C goto HFC_E1 ; < 680uS movlw .16 ; 29 tics subwf HF_LEN,F btfss STATUS,C goto HFC_END ; < 1510uS goto HFC_E1 ; error ; ; time-out during frame -> end of frame ; HFC_1 bcf FHF_PRG ; end of frame swapf HF_VAR,f ; 4 bits received -> MSB goto HFC_CHR ; validate the received part of byte ; ; full bit received ; HFC_OK decfsz HF_CNT,F goto HFC_END ; ; full byte received ; HFC_BOK movlw .8 movwf HF_CNT ; bit counter = 8 HFC_CHR movfw HF_POS btfss STATUS,Z goto HFC_COK ; ; first byte. Check start synchro byte ; HFC_STR movlw 0x0a xorwf HF_VAR,W btfss STATUS,Z goto HFC_ERR bsf LED ;LED ON ; store received byte in HF buffer HFC_COK movlw HFBUF addwf HF_POS,W movwf FSR movfw HF_VAR movwf INDF incf HF_POS,W xorlw .6 ; end of frame ? btfsc STATUS,Z goto HFC_SND xorlw .6 ; get back HF_POS value movwf HF_POS ; store it clrf HF_VAR goto HFC_END ; ; timing error -> reject frame ; HFC_ERR bcf FHF_PRG bcf LED ;LED OFF goto HFC_END ; ; frame is received... Send it to host ; HFC_SND bsf FTX_SND bcf FHF_PRG bcf LED ;LED OFF HFC_END bcf FHF_TOU ; clear possible time-out flag return ;****************************************************************** ; ; Decode WS type frames ; WS_DINX btfss FHF_INP ; frame in progress goto WS_B0 goto WS_B1 ; ; process data length ; WS_B1 ; data = 1 / check length movlw .5 ; 5 tics subwf HF_LEN,F btfss STATUS,C goto WS_E1 ; < 260uS -> error movlw .6 ; 11 tics subwf HF_LEN,F btfss STATUS,C goto WS_V1 ; < 570uS movlw .8 ; 19 tics subwf HF_LEN,F btfss STATUS,C goto WS_V0 ; < 1000uS WS_E1 ; incorrect length < 260uS or length > 1000uS goto WS_ERR ; ; length of data1 < 780uS => bit=1 ; WS_V1 bsf STATUS,C goto WS_V ; ; length of data1 < 1510uS => bit=0 ; WS_V0 bcf STATUS,C WS_V rlf HF_VAR,f goto WS_END ; ; data = 0 / check length ; movlw .5 ; 5 tics subwf HF_LEN,F btfss STATUS,C goto WS_E1 ; < 260uS -> error movlw .6 ; 11 tics subwf HF_LEN,F btfss STATUS,C goto WS_V1 ; < 570uS movlw .8 ; 19 tics subwf HF_LEN,F btfss STATUS,C goto WS_V0 ; < 1000uS WS_B0 btfsc FHF_TOU ; timeout ? goto WS_1 movlw .5 ; 5 tics subwf HF_LEN,F btfss STATUS,C goto WS_E1 ; < 260uS -> error movlw .6 ; 11 tics subwf HF_LEN,F btfss STATUS,C goto WS_B00 ; < 570uS movlw .8 ; 19 tics subwf HF_LEN,F btfsc STATUS,C goto WS_E1 ; > 1000 -> error WS_B01 btfss HF_VAR,0 goto WS_E1 ; bit Error goto WS_OK ; bit OK WS_B00 btfsc HF_VAR,0 goto WS_E1 ; bit Error goto WS_OK ; bit OK ; ; time-out during frame -> end of frame ; WS_1 bcf FHF_PRG ; end of frame movfw HF_POS btfsc STATUS,Z goto WS_ERR ; incomplete first byte goto WS_3 WS_2 bcf STATUS,C rlf HF_VAR,F ; pad with zeroes WS_3 decfsz HF_CNT,F goto WS_2 movlw HFBUF addwf HF_POS,W movwf FSR movfw HF_VAR movwf INDF incf HF_POS,F goto WS_SEND ; ; full bit received ; WS_OK decfsz HF_CNT,F goto WS_END ; ; full byte received ; WS_BOK movlw .8 movwf HF_CNT ; bit counter = 8 WS_CHR movfw HF_POS btfss STATUS,Z goto WS_COK ; ; first byte. Check start synchro byte ; WS_STR movlw 0x00 xorwf HF_VAR,W btfss STATUS,Z goto WS_ERR bsf LED ;LED ON ; store received byte in HF buffer WS_COK movlw HFBUF addwf HF_POS,W movwf FSR movfw HF_VAR movwf INDF incf HF_POS,W xorlw HFLEN ; maxframe size? btfsc STATUS,Z goto WS_SEND xorlw HFLEN ; get back HF_POS value movwf HF_POS ; store it clrf HF_VAR goto WS_END ; ; timing error -> reject frame ; WS_ERR bcf FHF_PRG bcf LED ;LED OFF goto WS_END ; ; frame is received... Send it to host ; WS_SEND bsf FWS_SND bcf FHF_PRG bcf LED ;LED OFF WS_END bcf FHF_TOU ; clear possible time-out flag return ;****************************************************************** ; ; INCSEQ - increment the sequence number ; never goes to 0 (from 0x1 to 0xf) ; INCSEQ incf SEQNCE,f movf SEQNCE,W xorlw 0x10 btfsc STATUS,Z swapf SEQNCE,f return ;****************************************************************** ; ; DEL100 - Delay 100ms ; not used in main loop ; DEL100 movlw .240 movwf COUNT clrf TEMP1 DELAY0 clrwdt nop nop decfsz TEMP1,f goto $+2 decfsz COUNT,f goto DELAY0 return ;****************************************************************** ; ; End of program ; end