	list p=p12f1840
	include <p12f1840.inc>
	__CONFIG _CONFIG1, _MCLRE_OFF & _WDTE_OFF
	__CONFIG _CONFIG2, _LVP_OFF

#define TXPIN 2
#define RXPIN 4
        
        cblock 0x20
        wait1
        iter
        input
        got
        tmp
        endc
        
        org 0

        ;;; Define pin 5 (RA2) as output
	movlb 0     ; select bank 0 (PORTA)
	clrf 0x0C   ; clear PORTA
	movlb 2     ; select bank 2 (LATA)
	clrf 0x0C   ; clear LATA
	movlb 3     ; select bank 3 (ANSELA)
	clrf 0x0C   ; clear ANSELA
	movlb 1     ; select bank 1 (TRISA)
        ;; TRISA (0: output, 1: input)
	bcf 0x0C, TXPIN
	bsf 0x0C, RXPIN

        ;;; program
	movlb 0                 ; select bank 0 (PORTA)

        bsf 0x0C, TXPIN         ; init tx

loop0:
        btfsc 0x0C, RXPIN           ; loop while input is high
        bra $-1
        call get

        movf got, 0
        call send

        goto loop0


get:    ;; get contents of W over 1200 baud
        ;; wait 1200 baud (1.2ms)
        ;; wait instructions 500 khz / 4 c/i / 1200 ms = 104.17

        clrf got                 ; ready output
        movlw 0x08
	movwf iter              ; set up iterator

        ;; wait half a tick
        movlw 0x0E
        call waiti

        movlw 0x1F              ; wait past start bit
        call waiti
        goto loop1
shift:
        lsrf got, 1             ; right shift got
loop1:  
        btfsc 0x0C, RXPIN           ; if current bit = 1
        bsf got, 7              ; set got:0 = 1
        ;; wait a tick (100)
        movlw 0x20
        call waiti
        decfsz iter, 1
        goto shift
        
        return
        
        
send:   ;; send contents of W over 1200 baud
        ;; wait 1200 baud (1.2ms)
        ;; wait instructions 500 khz / 4 c/i / 1200 ms = 104.17
        movwf input              ; store W in input

        movlw 0x08
	movwf iter              ; set up iterator

	movlb 0                 ; select bank 0 (PORTA)
	bcf 0x0C, TXPIN             ; transmit start bit
        
loop2:
        ;; wait 104 - 9 = 95
        movlw 0x1E
        call waiti

        btfss input, 0          ; if bit = 0
        bcf 0x0C, TXPIN         ; transmit a 0
        btfsc input, 0          ; if bit = 1
        bsf 0x0C, TXPIN         ; transmit a 1
        lsrf input, 1           ; left shift 0x20 by 1

        decfsz iter, 1          ; while bits left to transmit
        goto loop2

        ;; wait 102 - 2 = 100
        movlw 0x20
        call waiti
        
	bsf 0x0C, TXPIN             ; transmit stop bit

        movlw 0x24              ; wait > 104 instructions
        call waiti
        
        return


waiti:
        ;; W - 0x1E: wait 94 instructions
        ;; W = 0x1F: wait 97 instructions
        ;; W = 0x20: wait 100 instructions
        ;; wait 95 instructions
        ;; 4 + 1 + x * (1 + 2) - 1 = 4 + 3x
        movwf wait1
        decfsz wait1, 1
        bra $-1
        return

        end
