;	TITLE "--- Grip Program v0.1 ---"
;	LIST   P=16C84,R=HEX
;
;****************************************
;*					*
;*  ARRL (ISSL) Grip Controller		*
;*					*
;*   VERSION : 20 Jan, 1994		*
;*   (c) Ian King			*
;*					*
;*   PIC MODE = PIC16C84     CLK=4.0MHZ	*
;****************************************
;

#include "pic14"

config # "Grip Switch to RS232 Converter" ;
config pic	1684 ;
config clk	hs 4000000 ;
config cp	disabled ;
config wdt	enabled ;
config pwrup	enabled ;
config id	0xffff 0xffff 0xffff 0xffff ;
config # "... The End ..." ;


;
; Program Description
; -------------------
;
; This program reads 8 digital inputs
; and each time they change outputs a
; serial packet with RS232 timing
;
; The serial protocol used is:-
;      1200 Baud, 8 data, No Parity, 1 stop bit
;
; include file contains register information
; "standard" for 16C84
;

#include "reg.inc"

;
; Register File Allocation
;
	OutputByte	equ	0x0c	; byte to be serially
					; output
	KeySwitches	equ	0x0d	; current value of the
					; buttons on port B
	BitCount	equ	0x0e	; Bit Counter for RS232
	Delay		equ	0x0f	; Delay loop counter

;
; Bits Definitions
;
	TD		equ	1	; PortA 1 is the transmit
					; data pin
;
;*******************************************

	begin

		org 0x0000

boot:		goto main		; reset vector

		org 0x0004

irq:		goto main		; interrupt vector

		org 0x0005

;*******************************************

;
;===========================================
;  Bit_Delay
;  This routine gives the delay for one
;  serial bit at the desired baud rate
;  minus four t_states.  This is a really
;  heuristic amount, but the tolerance for
;  1200 baud is quite generous ;-) at 1 MIP
;
;  This allows two instuctions + the call
;  to Bit_Delay for precise timing.
;
;  The delay should be 1/1200 - 4 t_states
;  i.e. 0.83333 msec - 4 t_states
;
;  For a 4MHz Processor (1usec per t_state)
;  this gives us the equivalent of 833.3 - 4
;  t_states. So Bit_Delay pauses 829 t_states 
;===========================================
;

Bit_Delay:	movlw  206		; loop setup
		movwf  Delay

bitloop:	nop

		decfsz Delay, F		; djnz loop
		goto   bitloop

		nop			; tune for precise time
		nop
		return

;
;===========================================
; Send_Byte
; This routine sends a serial byte including
; start, data, parity and stop bits
;
; The data sent is in location OutputByte
;===========================================
;

Send_Byte:	bcf    porta, TD	; send start bit
		call   Bit_Delay	; wait one bit time

		movlw  8		; set number of bits
		movwf  BitCount		; to be sent

serialloop:	rrf    OutputByte, F	; move lsb to carry

		btfsc  status, c	; if 1 set output
		bsf    porta, TD

		btfss  status, c	; if 0 clear output
		bcf    porta, TD

		call   Bit_Delay	; wait one bit time

		decfsz BitCount, F	; loop if not finished
		goto   serialloop	

		bsf    porta, TD	; send stop bit
		call   Bit_Delay	; ensure at least one bit!
		call   Bit_Delay	; (twice because delay is
					; slightly shorter than bit time)

		return
;
;===========================================
; Kick_Watch
; Resets the watchdog timer and resets the
; prescaler for another
;
; The watchdog is set for about 1 second
;===========================================
;

Kick_Watch:	clrwdt			; clear the watchdog timer
		movlw  0b00100000	; Set up for page 1
		movwf  status		;
		movlw  0b10001110	; Set the option register 
		movwf  optn		; (prescale 64:1)
		clrf   status		; Set back to page 0
		return

;
;===========================================
; main
; This routine is the main entry point for
; the grip controller
; intialisation takes place and the main loop
; is controlled within this routine
;===========================================
;

main:		bcf    intcon,gie	; Disable interrupts

		clrf   pclath		; Everything within pclath=0

		call   Kick_Watch	; Reset Watchdog timer and
					; Setup Option Register

		movlw  0b00100000	; Set up for page 1
		movwf  status		;
		movlw  0b11111101	; Setup PortA RA1 is output
		movwf  trisa
		movlw  0b11111111	; Setup PortB as all inputs
		movwf  trisb
		clrf   status		; Set back to page 0

		clrf   KeySwitches	; Clear the keyswitch register

		clrf   pclath		; everything within low block

mainloop:	call   Kick_Watch	; Reset Watchdog timer

		movf   portb,W		; get the current button values
		andlw  0b11111110	; PA0 is reserved for a possible
					; output port so mask it off
		movwf  OutputByte	; use as tmp location

		subwf  KeySwitches,W	; use as a compare
		btfsc  status,z
		goto   mainloop		; if same repeat loop

		movf   OutputByte,W	; update current switch value
		movwf  KeySwitches

		clrf   pclath
		call   Send_Byte	; output the keyvalues
		
		goto   mainloop		; infinite loop

	end
;
; ... The End ...
;
;*******************************************
