;Jeff Mucha
;pic microcontroler code for exercising multi color LEDs in the probe tip
;Porta bits 0 1 2 3 4 are inputs where active low switches are attached.
;proper debouncing is required.
;Portb bit 1 is bit banging SCL on the I2C interface
;Portb bit 2 is bit banging SDA on the I2C interface
;Portb bit 0 is used to detect a probe being attached
;Portb bit 3 is used to turn on and off the trace color LED
;external clock is devided by 4 to provide internal clock most all instructions take 1 internal cycle
;////////////////
;This code Generates an I2C interface to control multi-element LEDs
;

	list	p=16f84
	radix	hex
#define SCL	1		;I2C port pin number
#define SDA	2		;I2C port pin number
#define tri_wr	b'00001001'	;set the SDA and SCL as outputs
#define tri_re	b'00001101'	;set SDA as an input


;--------------------------------------------------;
;equates
;--------------------------------------------------;
pc	equ	0x02
f	equ	0x01
porta	equ	0x05
portb	equ	0x06
status	equ	0x03

counter	equ	0x0c	;general purpose counter

table_val	equ	0x0d
table_off	equ	0x0e
counter2	equ	0x0f	;general purpose counter2


address_reg	equ	0x10	; address byte
inst_reg	equ	0x11	; instruction byte
scratch_reg	equ	0x12	; scratch
data_blue	equ	0x13	; data byte
data_green	equ	0x14	; data byte
data_red	equ	0x15	; data byte

stord_red	equ	0x16	; data byte
stord_green	equ	0x17	; data byte
stord_blue	equ	0x18	; data byte

reset_reg	equ	0x19	; reset byte, b0 = idle routine

;--------------------------------------------------;
;main program
;--------------------------------------------------;


	org	0x000
start	movlw	tri_wr		;set i2c as outputs
	tris	portb
	movlw	0xff		;set port a all inputs
	tris	porta
	


	movlw	b'00000000'	
	movwf	table_val	;reset variables
	movwf	counter
	movwf	reset_reg

	
	movlw	b'00000110'
	movwf	portb

	movlw	b'01001000'   ; address byte
	movwf	address_reg

	movlw	b'00000101'   ; instruction byte write red
	movwf	inst_reg

	movlw	b'00101100'   ; init data
	movwf	data_blue

	movlw	b'00100011'   ; init data
	movwf	data_green

	movlw	b'00011010'   ; init data
	movwf	data_red
	
	call 	wr_i2c		; reset everything
	
	bsf	portb,7		; trigger
	nop
	bcf	portb,7

	goto	scan
;---------------------------------------------------------
; lookup table
;--------------------------------------------------------

table	addwf	pc,f	;blue lookup table
	nop

	retlw	b'00011010'	;	green
	retlw	b'00111111'
	retlw	b'00101100'
		
	retlw	b'00111011'	;	Yellow
	retlw	b'00111111'
	retlw	b'00101100'

	retlw	b'00011010'	;	blue
	retlw	b'00111011'
	retlw	b'00111111'		

	retlw	b'00111111'	;	purple
	retlw	b'00100011'
	retlw	b'00111111'
;----------------------------------------------------------
;Scan the input pins
;----------------------------------------------------------

scan	movlw	b'00011111'		;port a bits 0,1,2,3 set high means no buttons pushed	
	subwf	porta,w			;compare w to port a using the subtract and then z flag check
	btfss	status,2
	goto	select

	btfss	portb,0
	call	delay
	


	btfsc	portb,3	;c
	call	idle
	
	btfsc	reset_reg,0	; skip instruction if bit clear
	btfsc	portb,3	;c	; skip if clear
	goto	scan
	
	call 	wr_i2c
	bcf	reset_reg,0
	goto 	scan



	
select	btfss	porta,0	
	call	setr

	btfss	porta,1	
	call	setg

	btfss	porta,2	
	call	setb

	btfss	porta,3	
	call	set_tbl

	goto    scan



;----------------------------------------------
; color increment routines
;----------------------------------------------
	
setr	incf	data_red,f
	call	wr_i2c
	
testr	btfss	porta,0		
	goto	testr
	goto	scan


setg	incf	data_green,f
	call	wr_i2c
	
testg	btfss	porta,1		
	goto	testg
	goto	scan

setb	incf	data_blue,f
	call	wr_i2c
	
testb	btfss	porta,2		
	goto	testb
	goto	scan

;---------------------------------------------------
; Delay routine
;---------------------------------------------------


	

delay	movlw	b'11111111'   ;set conter to highest value
	movwf	counter
	movwf	counter2

	
dloop	movwf	counter2
dloop2	decfsz	counter2,f
	goto 	dloop2
	
	decfsz	counter,f
	goto	dloop
	call	wr_i2c
	return

;---------------------------------------------------
; lookup table routine
;------------------------------------------

set_tbl incf	table_val,f		;increment color table	
	movfw	table_val		;set table value for offset
	call	table
	movwf	data_red

	incf	table_val,f		;increment color table	
	movfw	table_val		;set table value for offset
	call	table
	movwf	data_green

	incf	table_val,f		;increment color table	
	movfw	table_val		;set table value for offset
	call	table
	movwf	data_blue

	call	wr_i2c

	movlw	d'12'			;set to the number of entrys in the table	
	subwf	table_val,w		;compare w to table value using the subtract and then z flag check
	btfsc	status,2
	clrf	table_val


	
	
test_tb	btfss	porta,3		
	goto	test_tb
	return




;------------------------------------------
; Routine for setting the inactive color
;---------------------------------------

	

idle	movf	data_red,w
	movwf	stord_red
	movf	data_green,w
	movwf	stord_green
	movf	data_blue,w
	movwf	stord_blue

	movlw	b'00101100'   ; idle data	
	movwf	data_blue

	movlw	b'00100011'   ; idle data
	movwf	data_green

	movlw	b'00011111'   ; idel data
	movwf	data_red

	call	wr_i2c
	
	movf	stord_red,w
	movwf	data_red
	movf	stord_green,w
	movwf	data_green
	movf	stord_blue,w
	movwf	data_blue
	
	bsf	reset_reg,0
	return



; old code

stop	nop	
	goto 	stop
	

;------------------------------------------------------------	  
; Write Byte Serial routine
;------------------------------------------------------------
; Set the inst_reg and data_reg to set the value for the dac
; to be set	

wr_i2c	movlw	tri_wr   	; set tris register for writing
	tris	portb	
	bcf	portb,SDA	; Start bit  


	movf	address_reg,w
	movwf	scratch_reg
	call 	byte

	movf	inst_reg,w
	movwf	scratch_reg
	call 	byte
	
	movf	data_blue,w
	movwf	scratch_reg
	call 	byte

	movf	data_green,w
	movwf	scratch_reg
	call 	byte

	movf	data_red,w
	movwf	scratch_reg
	call 	byte
	
	bsf	portb,SCL	
	nop
	bsf	portb,SDA	; Stop bit
	
	return


byte	movlw	0x08		; set counter to 8 bits for shifting
	movwf	counter

loop1	bcf	portb,SCL	; set clock low for setup time
	rlf     scratch_reg,f   ; rotate data through carry
	btfsc	status,0	; test the carry bit
	bsf	portb,SDA	; set SFD high
	btfss	status,0
	bcf	portb,SDA	; set SDA low
	nop
	bsf	portb,SCL
	decfsz	counter
	goto	loop1

ak1	bcf	portb,SCL	; set clock line low
	movlw	tri_re		; set data line tristate		
	tris	portb			
	bsf	portb,SCL	; set clock line high
	nop			; test ack bit
	bcf	portb,SCL	; set clock line low
	movlw	tri_wr		; set data line write
	tris	portb
	
	return
	
	end
