;******************************************************************************
;*                                                                            *
;*  PIC12C508 version of RC to RS232       (C)  By K. Hewitt     Nov 2001     *
;*  Ver 2.2 Drives RS232 via resistor                                         *
;*  1 transistor input stage                                                  * 
;******************************************************************************
;        LIST P=16C54, F=INHX8M, R=HEX

        include "C:\mydata~1\PIC\PICREG.EQU"
;******************************************************************************
;*  Set up varibles and values                                                *
;******************************************************************************
DX        equ     0               ;Set bit for TX to bit 0
RX        equ     3H              ;Set bit 3 for PPM ip 
Width     equ     0CH             ;F12 to count pulse width
XCount    equ     0DH             ;F13 to hold TX bit count
XmtReg    equ     0EH             ;F14 to hold TX character
Delayreg  equ     0FH             ;F15 to hold delay loop
Chars     equ     10H             ;F16 Number of chars to send
Txchar    equ     11H             ;F17 pointer to tx char
Txcount   equ     12H             ;F18 Tx char loop counter

;******************************************************************************
;*  Start of program                                                          *
;******************************************************************************
        ORG     0               ;set start of program to 000 hex
        movwf   OSCCAL
Begin   
        clrf    PORT_B
        movlw   B'11111110'       ;set bit 0 for output
        tris    PORT_B

;***********************************************************
;* Main program loop, it starts by waiting for RX line to  *
;* go low then as soon RX goes Hi it calls the routine to  *
;* measure the pulse width. On return from this routine if *
;* the pulse was the sync pulse then it starts to measure  *
;* the width of the pulses when it finds the next sync it  *
;* calls the routine to send the ASCII data                *
;***********************************************************

Find_sync
Hi        btfss   PORT_B,RX       ;is RX line Hi
          goto    Hi              ;Yes
Lo        btfsc   PORT_B,RX       ;RX line is lo wait to go Hi
          goto    Lo              ;RX line lo
          call    Measure         ;Call routine to measure width
          tstf    Width		  ;Find status of width
          bnz     Hi              ;Not zero so not sync try again
          goto    Readings	  ;Zero so it is sync pulse
          goto    Find_sync       ;Go and find next sync pulse

Readings  movlw   02H             ;Set chars to 2 (sync + buttons)
          movwf   Chars           ;
          movlw   17H             ;Set start of TX buffer to F23
          movwf   FSR             ;
Hi_1      btfss   PORT_B,RX       ;is RX line Hi
          goto    Hi_1            ;Yes
Lo_1      btfsc   PORT_B,RX       ;RX line is lo wait to go Hi
          goto    Lo_1            ;RX line lo
          call    Measure         ;Call routine to measure width
          tstf    Width		  ;Find status of width
          bnz     Pulse           ;Not zero,so not sync read next pulse
          goto    Send            ;Zero so it is sync pulse

Pulse     incf    Chars,1         ;Inc number of chars to send
          movf    Width,0         ;Save width measurement
          movwf   0               ;to TX buffer position Txchar
          incf    FSR,1           ;Inc TX buffer pointer
          goto    Lo_1            ;Go wait for start of next pulse


;************************************************************
;* This routine measures the width of positive going pulses *
;* and returns with a value >0 for pulses up to 2.55mS or a *
;* value of 0 if it is the sync pulse.                      *
;************************************************************

Measure   clrf     Width          ;Clear F8 to zero
Repeat    nop                     ;Five NOP's to pad
          nop                     ;out routine to give
          nop                     ;a total loop time of
          nop                     ;10uS
          nop                     ;
          btfsc   PORT_B,RX       ;is RX lo
          goto    Done            ;Yes go to Done
          incfsz  Width,1         ;Inc width count
          goto    Repeat          ;loop for another 10uS
Done      retlw   0               ;return from routine


;************************************************************
;* This routine is called when the sync pulse is found and  *
;* it sends a sync char (240 dec)+the number of chars in    *
;* this TX packet(max 15 chars) then a char representing    *
;* the status of the push buttons and then chars for how    *
;* ever many pulse width measurements where taken.          *
;************************************************************

Send      movlw   15H             ;Set pointer to F21
          movwf   Txchar          ;
          movlw   .240            ;Set 1st char of TX buffer to sync
          movwf   15H             ;Store in F21
          movf    Chars,0         ;Set W to number of TX chars
          addwf   15H,1           ;Add W to 240
          movlw	  0		  ;Read button status
          movwf   16H             ;Saved in 2nd char of TX buffer

          movf    Chars,0         ;Set W to Chars
          movwf   Txcount         ;Set tx loop to chars
          movf    Txchar,0        ;set W to first tx char
          movwf   FSR             ;Set FSR to Txchar

Loop2     movf    0,0             ;Get Next char
          movwf   XmtReg          ;Copy to XmtReg

Xmtr      movlw   8
          movwf   XCount          ;8 data bits
          bsf     PORT_B,DX       ;Send start bit
X_next    call    Delay94         ;Delay 94uS to make total 104uS
          rrf     XmtReg          ;Shift character right 1 bit
          btfsc   STATUS,CARRY    ;Test bit to be transmitted
          bcf     PORT_B,DX       ;Bit is a 1
          btfss   STATUS,CARRY
          bsf     PORT_B,DX       ;Bit is a 0
          decfsz  XCount          ;If Count=0 then send a stop bit
          goto    X_next          ;Transmit next bit

X_Stop    call    Delay101        ;101uS
          bcf     PORT_B,DX       ;Send stop bit
          call    Delay102        ;102uS


          incf    FSR,1           ;inc pointer to next char
          decfsz  Txcount         ;Dec loop counter
          goto    Loop2           ;Send next Char
X_Over    goto    Find_sync       ;return back


;*************************************************************
;* This routine provides the different delays needed by the  *
;* serial TX routine the delay is decided by the entery point*
;*************************************************************
Delay102  nop                     ;Delay of 102uS to retlw
Delay101  nop                     ;Delay of 101uS to retlw
          nop
          nop
          nop
          nop
          nop
          nop
Delay94   movlw   .22             ;Set delay loop value to 22 decimal
          movwf   Delayreg        ;22*(1+1+2)uS = 88uS

Delay1    nop                     ;Total delay from Delay94
          decfsz  Delayreg,1      ;Decrement F18 by 1
          goto    Delay1          ;to retlw = 94uS
          nop
          nop
          retlw   0

          End