; LghtCtrl - Light Bulb Controller - by Chris Cole
; 16F84 running at 10MHz - 9600 baud, 1bit=104uS => 260.4 cycles
; pins: 6=Rx, 7=Tx, 4=10kohm->+5V, 5=gnd, 14=+5V, 15&16=10/12MHz xtal, 17=to light
; NOTE: Be sure to set the com port for 9600,N,8,1 and NO FLOW CONTROL!

	TITLE	"LghtCtrl"	
	LIST	P=16F84a

	__CONFIG _CP_OFF & _WDT_OFF & _HS_OSC;

#include "C:\progra~1\mplab\p16f84a.inc" ;

#define RXpin232	PORTB,0	; (pin 6)
#define TXpin232	PORTB,1	; (pin 7)
#define LightBulb	PORTA,0	; (pin 17)
				;
RAMbase	EQU	0x0c		;
				;
; DNOP - Double NOP. Delay of 2 cycles, takes only one instruction ;
DNOP	MACRO			;
	LOCAL	Label		;
Label	GOTO	Label+1		;
	ENDM			;
				;
; Delay3W - Delay 3 * W cycles, three instructions ;
Delay3W	MACRO			;
	LOCAL	Label		;
	MOVWF	Delay		;
Label	DECFSZ	Delay		;
	GOTO	Label		;
	ENDM			;
				;
; Declarations			;
	CBLOCK	RAMbase		;
		Count		;
		Delay		;
		BitsToGo	;
		SerByte		;
	ENDC			;
				;
	ORG	0		;
	GOTO	Main		;
;----------------------------------------------------------------------------------------------------
Main				;
	bsf	STATUS, RP0	;
	movlw	b'00000'	; RA0 all outputs
	movwf	TRISA		;
	movlw	b'11111101'	; RB1=output, rest inputs
	movwf	TRISB		;
	bcf	STATUS, RP0	;
Init				;
	bsf	TXpin232	; set up initial states
	bcf	LightBulb	; Turn off light initially
	movlw	'R'		;
	call	SendChar232	;
	movlw	'e'		;
	call	SendChar232	;
	movlw	'a'		;
	call	SendChar232	;
	movlw	'd'		;
	call	SendChar232	;
	movlw	'y'		;
	call	SendChar232	;
	movlw	'.'		;
	call	SendChar232	;
	movlw	0x0a		;
	call	SendChar232	;
	movlw	0x0d		;
	call	SendChar232	;
MainLoop			; wait here for incoming 232 Cmd.
	call	Wait232		; 
	movwf	SerByte		;
	movlw	'1'		; Turn Light ON
	xorwf	SerByte,w	; compare
	btfsc	STATUS,Z	; is this a match?
	  goto	TurnON		;
	movlw	'0'		; Turn Light OFF
	xorwf	SerByte,w	; compare
	btfsc	STATUS,Z	; is this a match?
	  goto	TurnOFF		;
	movlw	'?'		; Show current state of light
	xorwf	SerByte,w	; compare
	btfsc	STATUS,Z	; is this a match?
	  goto	ShowState	;
	goto	MainLoop	;
;----------------------------------------------------------------------------------------------------
TurnON				;
	bsf	LightBulb	; turn on the light
	goto	SendON		;
;----------------------------------------------------------------------------------------------------
TurnOFF				;
	bcf	LightBulb	; turn off the light
	goto	SendOFF		;
;----------------------------------------------------------------------------------------------------
SendON				;
	movlw	'O'		;
	call	SendChar232	;
	movlw	'N'		;
	call	SendChar232	;
	movlw	0x0a		;
	call	SendChar232	;
	movlw	0x0d		;
	call	SendChar232	;
	goto	MainLoop	;
;----------------------------------------------------------------------------------------------------
SendOFF				;
	movlw	'O'		;
	call	SendChar232	;
	movlw	'F'		;
	call	SendChar232	;
	movlw	'F'		;
	call	SendChar232	;
	movlw	0x0a		;
	call	SendChar232	;
	movlw	0x0d		;
	call	SendChar232	;
	goto	MainLoop	;
;----------------------------------------------------------------------------------------------------
ShowState			;
	movlw	'L'		;
	call	SendChar232	;
	movlw	'i'		;
	call	SendChar232	;
	movlw	'g'		;
	call	SendChar232	;
	movlw	'h'		;
	call	SendChar232	;
	movlw	't'		;
	call	SendChar232	;
	movlw	' '		;
	call	SendChar232	;
	movlw	'i'		;
	call	SendChar232	;
	movlw	's'		;
	call	SendChar232	;
	movlw	' '		;
	call	SendChar232	;
	btfsc	LightBulb	;
	  goto	SendON		;
	goto	SendOFF		;
;----------------------------------------------------------------------------------------------------
Wait232				;
	btfsc	RXpin232	;
	  goto	Wait232		;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Get232				; returns serial value in w register
	movlw	8		;
	movwf	BitsToGo	;
	movlw	0x82		;
	Delay3W			; wait for startbit to pass and get into middle of first bit
GetNextBit232			;
	bcf	STATUS,C	; [1] zero out CARRY to begin with
	btfsc	RXpin232	; [1]
	  bsf	STATUS,C	; [1]
	rrf	SerByte		; [1] rotate right, bring in carry bit on left side
	movlw	0x54		; [1]
	Delay3W			; [252]
	decfsz	BitsToGo	; [1]
	  goto	GetNextBit232	; [2]
	movf	SerByte,w	;
	return			;
;----------------------------------------------------------------------------------------------------
SendChar232			;
	movwf	SerByte		; store char to send out
	movlw	8		;
	movwf	BitsToGo	; # bits to send out
	bcf	TXpin232	; send out start bit
	movlw	0x56		; [1] set length for start bit
	Delay3W			; [258]
TXLoop232			;
	rrf	SerByte		; [1]
	btfsc	STATUS,C	; [1] is it a 1?
	  goto	TXOne232	; [2] yes - send a '1'
	bcf	TXpin232	; [1]
	nop			; [1]
	movlw	0x54		; [1]
	Delay3W			; [252]
	decfsz	BitsToGo	; [1]
	  goto	TXLoop232	; [2]
	goto	DoneByte232	;
TXOne232			;
	bsf	TXpin232	; [1]
	movlw	0x54		; [1]
	Delay3W			; [252]
	decfsz	BitsToGo	; [1]
	  goto	TXLoop232	; [2]
DoneByte232			;
	bsf	TXpin232	; [1] send out stop bit
	movlw	0x54		; [1]
	Delay3W			; [252]
	bsf	TXpin232	; idle state for TXpin
	return			;
;----------------------------------------------------------------------------------------------------
	END			;


