please dont rip this site
		;
		;**********************************************************************
		; i2ccmd.asm	- Polled and Interrupt based I2C and EEPROM routines
		;**********************************************************************
		;
		; John E. Andrews
		; April 3rd, 1998
		;
		; The following functions are included:
		;  InitI2C	; init the SSP peripheral and variables for I2C operation
		;  I2CRead	; read one byte from i2c address x
		;  I2CWrite	; write an x parameter to i2c addr x
		;  EERead	; read eeprom location x
		;  EEWrite	; write an x parameter into eeprom location x
		;  KickEERead	; read a string at eeprom location x via interrupts
		;  KickEEWrite	; write a string at eeprom location x via interrupts
		;  KickI2CRead	; read a string from an i2c slave via interrupts
		;  KickI2CWrt	; write reply addr, byte count and data to i2c addr 
		;  I2CIsr		; I2C interrupt service routine
		;
		; The init function and the routines to start i2c master data tranfers
		;  are called by inline code. The init function is called at reset and 
		;  the master data transfers are associated with PICos commands.
		; I2CIsr provides continuous interrupt based slave or master data
		;  transfers and is called from the peripheral interrupt vector. It is
		;  terminated by a return to the peripheral interrupt service routine
		;  which restores context and performs the retfie. 
		;
		; The default i2c slave address is defined here
	DfltSlvAddr	equ 0x23
		; This address is shifted 1 bit left and used to match the address
		;  supplied at the beginning of an i2c transfer. This makes the lsb
		;  a don't care which is used by i2c to provide Read/write info.
		; This address shouldn't be 0 since this is the general call address
		;  and it shouldn't be hex 50-5F since all 5x addresses are reserved 
		;  by eeprom devices. Valid addresses are from 1-4F and 60-7F.
		; This address can be changed at run time by the i2cAddr command.
		;
		; This data statement stores a constant ascii string in program 
		;  memory. Its copied to a ram buffer using the CpyTbl2Buf macro in
		;  InitI2C and is output during slave transmit by I2CIsr.
SlvRdD	; initial slave read data message
	data	"Va Tech Rules!",0
		;
		;**********************************************************************
InitI2C	; initialize I2C operation after device reset
		;**********************************************************************
		;
		; ***** Variables for I2C operation *****
		; 
	i2cRxBufferSize	equ 40			; size of buffer for slave Rx data
		;
	cblock							; declare bank 0 variables
		i2cState					; current I2C state
		i2cSlvAddr					; addr of i2c slave, 0-7F << 1, lsb=0
		; slave Rx buffer, allow extra char for 0 fill by command parser
		i2cRxBuffer:	i2cRxBufferSize+1
		i2cRxPtr					; pointer into Rx buffer used by inline code
		i2cIntRxPtr					; pointer into Rx buffer used by isr
		i2cDataPtr					; buffer pointer used for result output
		i2cAddr						; i2c addr for master transmit
		i2cRpyPend					; slave addr pending reply
		i2cRpyFncH					; function addr to involke on reply hi byte
		i2cRpyFncL					; function addr to involke on reply lo byte
		i2cByteCnt					; number of bytes in transfer packet
		i2cEEAddr					; addr in eeprom for current write cycle
		i2cFlags					; flag bits
		i2cSlvRdBuff:	20			; buffer holding data for slave read
		i2cSlvPtr					; isr pointer into i2cSlvRdBuff
	endc
		;
		; bit flag definitions for i2cFlags
	i2cRxRdy	equ	0
		;
		; ***** executable code to init I2C operation *****
		; 
		; This function label is called once after device reset
		movlw	DfltSlvAddr<<1		; load default i2c slave address
		movwf	i2cSlvAddr			;  into gpr storage location
		bcf		i2cSlvAddr, 0		; clear lsb for Read/write bit
		setf	i2cRpyPend			; init reply pending address to FF
		clrf	i2cFlags			; init all flags to off
		;
		; Init buffer to be transmitted on slave read
		CpyTbl2Buf	SlvRdD, i2cSlvRdBuff
		;
		; fall through to reset i2c to slave mode
		;
		;**********************************************************************
RstI2C	; reset the SSP peripheral and variables for I2C slave operation
		;**********************************************************************
		;
		; This function can be called by any routine wishing to reset the ssp
		;  to i2c slave operation. It sets up the SSP peripheral to provide 
		;  buffered, line based, interrupt driven i2c slave receive and polled
		;  and interrupt driven i2c master transmit. EEPROM write and read are
		;  also provided including interrupt state machine driven, buffered, 
		;  string input and output.
		;
		movlb	6					; select sfr bank for ssp
		movfp	i2cSlvAddr, WREG	; fetch i2c slave address and
		movwf	SSPADD				; load it into slave addr register
		movlw	0x36				; enable ssp, set CKP, select I2C slave
		movwf	SSPCON1				; in SSPCON1
		clrf	i2cState			; init i2c state to idle
		movlb	4					; select sfr bank for PIE2
		bcf		PIR2, SSPIF			; init interrupt flag
		bsf		PIE2, SSPIE			; enable SSP interrupts
		return
		;
		;*********************************************************************
		; i2c slave mode command functions
		;*********************************************************************
SetI2C	; load hexidecimal parameter into i2c slave address
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"I2CADDR=x\r", CmdPC, "Set I2C slave address = 0-7F\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		; copy hexidecimal parameter from buffer to SSPADD
		movlw	cmdPrmBuff			; load parameter buffer addr
		movwf	FSR1				; into FSR1
		movpf	INDF1, WREG			; copy parameter to W
		; shift address out of lsb which i2c uses for R/w bit
		rlncf	WREG				; shift address left 1` bit
		bcf		WREG, 0				; clear lsb
		movwf	i2cSlvAddr			; save in gpr
		call	RstI2C				; set i2c slave address in ssp
		; fall through to DspI2C
		;*********************************************************************
DspI2C	; create output string reporting i2c slave addr as a hex number
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"I2CADDR\r", CmdPC, "Display I2C slave address\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		; copy first part of output string into output buffer using FSR0
		CpyTbl2Out	SlvD
		; copy i2cSlvAddr value into output buffer as a hex number
		rrncf	i2cSlvAddr, W		; unshift i2c slave addr into W
		bcf		WREG, 7				; clear msb of unshifted addr
		movlb	1					; select SFR bank for PORTD
		movwf	PORTD				; display on portd LEDs
		call	Hex2Buf				; convert hex value into output buffer
		; copy hex = into same output buffer using FSR0
		CpyTbl2Out	HxEqD
		; display bits of address
		movlw	'0'					; load ascii 0 char into W
		btfsc	i2cSlvAddr, 7		; skip if msb is clear
		movlw	'1'					; load ascii 1 char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'0'					; load ascii 0 char into W
		btfsc	i2cSlvAddr, 6		; skip if nsb is clear
		movlw	'1'					; load ascii 1 char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'0'					; load ascii 0 char into W
		btfsc	i2cSlvAddr, 5		; skip if nsb is clear
		movlw	'1'					; load ascii 1 char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'0'					; load ascii 0 char into W
		btfsc	i2cSlvAddr, 4		; skip if nsb is clear
		movlw	'1'					; load ascii 1 char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	' '					; load ascii ' ' into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'0'					; load ascii 0 char into W
		btfsc	i2cSlvAddr, 3		; skip if nsb is clear
		movlw	'1'					; load ascii 1 char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'0'					; load ascii 0 char into W
		btfsc	i2cSlvAddr, 2		; skip if nsb is clear
		movlw	'1'					; load ascii 1 char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'0'					; load ascii 0 char into W
		btfsc	i2cSlvAddr, 1		; skip if lsb is clear
		movlw	'1'					; load ascii 1 char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'x'					; load ascii x char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'\n'				; load ascii LF char into W
		movwf	INDF0				; place char into output buffer
		incf	FSR0				; inc pointer to next char location
		movlw	'\r'				; load ascii CR into last location in buff
		movwf	INDF0				;  CR terminates cmd line when resubmited
		return						; return from Cmd
		; This is the end of the functions executable code
		;
		; These data statements store constant ascii output strings in program 
		;  memory. They're accessed using the CpyTbl2Out macro
SlvD	; constant string for slave addr display
	data	"\nI2C slave addr is ",0
HxEqD	; constant string for hex = display
	data	" hex = ",0
		;
		;*********************************************************************
		; i2c master mode data transfer command functions
		;*********************************************************************
Wait4SSPIF	macro	; this is equivalent to waiting for an ssp interrupt
		;*********************************************************************
		;
		; switch banks and wait for SSPIF, clear and switch back to ssp bank
		movlb	1					; select sfr bank for peripheral ints
		btfss	PIR1, SSPIF			; poll for interrupt flag
		goto	$-1					; until then wait
		bcf		PIR1, SSPIF			; s/w int flag clear
		movlb	6					; select sfr bank for ssp
	endm
		;
		;*********************************************************************
I2CRead	; read one byte from i2c address x
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"I2Cx\r", CmdPC, "Read byte at I2C addr x=0-7F\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		bsf		SSPCON2, SEN		; initiate a start condition
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, SEN		; skip once SEN is cleared
		goto	$-1					; until then wait
		movlw	cmdPrmBuff			; load addr of parameter buffer
		movwf	FSR1				; into FSR1
		rlncf	INDF1, W			; read shifted i2c address into W
		bsf		WREG, 0				; set R/w bit for read
		movwf	SSPBUF				; output i2c addr parameter
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, RCEN		; start receiving data byte
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfss	SSPSTAT, BF			; skip once BF is set
		goto	$-1					; until then wait
		btfsc	SSPCON2, RCEN		; skip once RCEN is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, ACKDT		; generate nack to terminate read
		bsf		SSPCON2, ACKEN		; start nack sequence
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, ACKEN		; skip once ACKEN is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, PEN		; initiate a stop sequence
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		; create output string reporting value of data byte
		; copy first part of output string into output buffer using FSR0
		CpyTbl2Out	I2CD
		; copy i2c addr into output buffer as a hex number
		movfp	INDF1, WREG			; read ee memory addr into W
		call	Hex2Buf				; convert hex value into output buffer
		; copy = into same output buffer using FSR0
		CpyTbl2Out	EqD
		; copy data byte into output buffer as a hexidecimal number
		movfp	SSPBUF, WREG		; read data byte into W
		call	Hex2Buf				; convert hex value into output buffer
		; put a LF and CR after the data
		movlw	'\n'				; load LF char
		movwf	INDF0				; put it into the output string
		incf	FSR0				; point to next output char location
		movlw	'\r'				; load ascii CR into last location in buff
		movwf	INDF0				;  CR terminates cmd line when resubmited
		call	RstI2C				; reset to i2c slave operation
		return						; return from Cmd
		; This is the end of the functions executable code
		;
		; These data statements store constant ascii output strings in program 
		;  memory. They're accessed using the CpyTbl2Out macro.
I2CD		; constant string for i2c display
	data	"\nI2C addr ",0
EqD		; constant string for = display
	data	" = ",0
		;
		;*********************************************************************
I2CWrite	; write an x parameter to i2c addr x
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"I2Cx=x\r", CmdPC, "Write x at I2C addr x=0-7F\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		bsf		SSPCON2, SEN		; initiate a start condition
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, SEN		; skip once SEN is cleared
		goto	$-1					; until then wait
		movlw	cmdPrmBuff			; load addr of start of parameter buffer
		movwf	FSR1				; into FSR1
		rlncf	INDF1, W			; read shifted i2c address into W
		bcf		WREG, 0				; clear R/w bit for write
		movwf	SSPBUF				; output i2c addr parameter
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	FSR1				; point to data parameter
		movpf	INDF1, SSPBUF		; write data parameter to i2c
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, PEN		; initiate a stop sequence
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		call	RstI2C				; reset to i2c slave operation
		return						; return null result string from Cmd
		;
		;*********************************************************************
EERead	; read eeprom location x
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"EEx\r", CmdPC, "Read byte at EEPROM addr x\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		movlw	cmdPrmBuff			; load addr of parameter buffer
		movwf	FSR1				; into FSR1
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		bsf		SSPCON2, SEN		; initiate a start condition
		Wait4SSPIF					; wait for SSPIF in PIR
		btfsc	SSPCON2, SEN		; skip once SEN is cleared
		goto	$-1					; until then wait
		movlw	0xA0				; load I2C addr parameter for ee write
		movwf	SSPBUF				; output I2C addr parameter for ee write
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		movpf	INDF1, SSPBUF		; output ee memory addr parameter  
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, RSEN		; initiate a restart condition
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, RSEN		; skip once RSEN is cleared
		goto	$-1					; until then wait
		movlw	0xA1				; load I2C addr parameter for ee read
		movwf	SSPBUF				; output I2C addr parameter for ee read
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, RCEN		; start receiving data byte
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfss	SSPSTAT, BF			; skip once BF is set
		goto	$-1					; until then wait
		btfsc	SSPCON2, RCEN		; skip once RCEN is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, ACKDT		; generate nack to terminate ee read
		bsf		SSPCON2, ACKEN		; start nack sequence
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, ACKEN		; skip once ACKEN is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, PEN		; initiate a stop sequence
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		; create output string reporting value of data byte
		; copy first part of output string into output buffer using FSR0
		CpyTbl2Out	EED
		; copy ee memory addr into output buffer as a hexidecimal number
		movfp	INDF1, WREG			; read ee memory addr into W
		call	Hex2Buf				; convert hex value into output buffer
		; copy = into same output buffer using FSR0
		CpyTbl2Out	EqD
		; copy data byte into output buffer as a hexidecimal number
		movfp	SSPBUF, WREG		; read data byte into W
		call	Hex2Buf				; convert hex value into output buffer
		; put a LF and CR after the data
		movlw	'\n'				; load LF char
		movwf	INDF0				; put it into the output string
		incf	FSR0				; point to next output char location
		movlw	'\r'				; load ascii CR into last location in buff
		movwf	INDF0				;  CR terminates cmd line when resubmited
		call	RstI2C				; reset to i2c slave operation
		return						; return from Cmd
		; This is the end of the functions executable code
		;
		; These data statements store constant ascii output strings in program 
		;  memory. They're accessed using the CpyTbl2Buf and CpyTblCont macros 
		;  with the addresses given by the labels.
EED		; constant string for ee display
	data	"\nEEPROM addr ",0
		;
		;*********************************************************************
EEWrite	; write an x parameter into eeprom location x
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"EEx=x\r", CmdPC, "Write x at EEPROM addr x\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		movlw	cmdPrmBuff			; load addr of start of parameter buffer
		movwf	FSR1				; into FSR1
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		bsf		SSPCON2, SEN		; initiate a start condition
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, SEN		; skip once SEN is cleared
		goto	$-1					; until then wait
		movlw	0xA0				; load I2C addr parameter for ee write
		movwf	SSPBUF				; output I2C addr parameter for ee write
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		movpf	INDF1, SSPBUF		; output ee memory addr parameter  
		Wait4SSPIF					; wait for SSPIF in PIR1
		incf	FSR1				; point to data parameter
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		movpf	INDF1, SSPBUF		; write data parameter to ee
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		bsf		SSPCON2, PEN		; initiate a stop sequence
		Wait4SSPIF					; wait for SSPIF in PIR1
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		call	RstI2C				; reset to i2c slave operation
		return						; return null result string from Cmd
		;
		;*********************************************************************
KickEERead	; read a string starting at eeprom location x via interrupts
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"S@EEx\r", CmdPC, "Read string starting at EEPROM addr x\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		; Initialize flags and pointers for interrupt based I2C master read.
		;
		; wait for any ongoing buffered I2C activity to complete
		tstfsz	i2cState			; skip when I2C xfer complete
		goto	$-1					; until then wait
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		movlw	.10					; load value for EERdStart into W
		movwf	i2cState			; set I2C state to read start complete
		movlb	4					; select sfr bank for PIE2
		bcf		PIR2, SSPIF			; init interrupt flag
		bsf		PIE2, SSPIE			; enable SSP interrupts
		movlb	6					; select sfr bank for ssp
		bsf		SSPCON2, SEN		; initiate a start sequence
		; the resulting interrupt kicks off the i2c int based state machine
		; wait here until int based I2C read is complete
		tstfsz	i2cState			; skip once state is idle
		goto	$-1					; until then wait
		return						; return result string built by I2CIsr
		;
		;**********************************************************************
KickEEWrite	; write a string starting at eeprom location x via interrupts
		;**********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"S@EEx=s\r", CmdPC, "Write s starting at EEPROM addr x\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		; This function initiates an interrupt driven, buffered, i2c master 
		;  write to eeprom memory. The i2c bus addr and R/w bit are constant
		;  0xA1 and 0xA0 respectively. The starting eeprom memory addr is 
		;  provided by Cmd in cmdPrmBuff[0] and an ascii, 0 terminated, string
		;  parameter follows.
		; An 8 byte eeprom write buffer size is assumed. When the least 
		;  significant three bits of the just completed ee write addr = 7 then
		;  stop, start, i2c addr and R/w, and ee momory addr sequences are
		;  performed by succesive SSPIF interrupts. Then the data write 
		;  interrupt sequence continues until the 0 termination is reached.
		;
		; Initialize flags and pointers for interrupt based I2C master write.
		;
		; wait for any ongoing buffered I2C activity to complete
		tstfsz	i2cState			; skip when I2C xfer complete
		goto	$-1					; until then wait
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		; init ee memory addr and ptr to ee data parameters
		movlw	cmdPrmBuff			; load cmd parameter buffer addr
		movwf	FSR1				; into FSR1
		movpf	INDF1, i2cEEAddr	; save ee memory write addr parameter
		incf	FSR1				; inc pointer to first data value
		movpf	FSR1, i2cDataPtr	; save ptr into I2C master buffer ptr
		; init ssp peripheral to 100KHz i2c master @ 16MHz
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		incf	i2cState			; set I2C state for write start complete
		movlb	4					; select sfr bank for PIE2
		bcf		PIR2, SSPIF			; init interrupt flag
		bsf		PIE2, SSPIE			; enable SSP interrupts
		movlb	6					; select sfr bank for ssp
		bsf		SSPCON2, SEN		; initiate a start sequence
		; the resulting interrupt kicks off the i2c int based state machine
		; wait here until int based I2C write is complete to prevent buffer crash
		tstfsz	i2cState			; skip once state is idle
		goto	$-1					; until then wait
		return						; I2C start initiated, return from Cmd
		;
		;*********************************************************************
KickI2CRead	; read a string from an i2c slave via interrupts
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"I2Cx:\r", CmdPC, "Read string from i2c slave addr x\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		; Initialize flags and pointers for interrupt based I2C master read.
		;
		; wait for any ongoing buffered I2C activity to complete
		tstfsz	i2cState			; skip when I2C xfer complete
		goto	$-1					; until then wait
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		movlw	.24					; load value for MstrRdStart into W
		movwf	i2cState			; set I2C state to read start complete
		movlb	4					; select sfr bank for PIE2
		bcf		PIR2, SSPIF			; init interrupt flag
		bsf		PIE2, SSPIE			; enable SSP interrupts
		movlb	6					; select sfr bank for ssp
		bsf		SSPCON2, SEN		; initiate a start sequence
		; the resulting interrupt kicks off the i2c int based state machine
		; wait here until int based I2C read is complete
		tstfsz	i2cState			; skip once state is idle
		goto	$-1					; until then wait
		return						; return result string built by I2CIsr
		;
		;**********************************************************************
KickI2CWrt	; write reply addr, byte count and data to i2c addr via interrupts
		;**********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"I2Cx:s\r", CmdPC, "Xfer s to I2C addr x for execution\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		; This function initiates an interrupt driven, buffered, i2c master 
		;  write to an i2c slave. The i2c slave addr is provided by Cmd in 
		;  cmdPrmBuff[0] and an ascii, 0 terminated, string parameter follows.
		; The characters in the string are counted and transmitted until the
		;  byte count is exhausted.
		;
		; Initialize flags and pointers for interrupt based I2C master write.
		;
		; wait for any ongoing buffered I2C activity to complete
		tstfsz	i2cState			; skip when I2C xfer complete
		goto	$-1					; until then wait
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		; init i2c addr
		movlw	cmdPrmBuff			; load cmd parameter buffer addr
		movwf	FSR1				; into FSR1
		movpf	INDF1, i2cAddr		; save i2c addr parameter into addr gpr
		rlncf	i2cAddr				; shift i2c addr out of lsb
		bcf		i2cAddr, 0			; clear lsb for write
		movpf	FSR1, i2cDataPtr	; save ptr prestart into master buffer ptr
		clrf	i2cByteCnt			; init byte count
		; loop here to count chars until 0 termination
		incf	FSR1				; inc to next char
		incf	i2cByteCnt			; inc byte count
		tstfsz	INDF1				; skip if current char is 0
		goto	$-3					; otherwise test next char
		movlw	0x0D				; load ascii CR char
		movwf	INDF1				; replace 0 with CR for input termination
		; init ssp peripheral to 100KHz i2c master @ 16MHz
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		movlw	.19					; load state number for master transmit
		movwf	i2cState			; set I2C state for write start complete
		movlb	4					; select sfr bank for PIE2
		bcf		PIR2, SSPIF			; init interrupt flag
		bsf		PIE2, SSPIE			; enable SSP interrupts
		movlb	6					; select sfr bank for ssp
		bsf		SSPCON2, SEN		; initiate a start sequence
		; the resulting interrupt kicks off the i2c int based state machine
		clrf	cmdOutBuff			; prevent new cmd line prompt
		return						; I2C start initiated, return from Cmd
		;
		;**********************************************************************
KickI2CRpy	; send reply to device which submitted command via i2c
		;**********************************************************************
		;
		; This function initiates an interrupt driven, buffered, i2c master 
		;  write to an i2c slave. The i2c slave addr is provided by Cmd in 
		;  cmdPrmBuff[0] and an ascii, 0 terminated, string parameter follows.
		; The characters in the string are counted and transmitted until the
		;  byte count is exhausted.
		;
		; Initialize flags and pointers for interrupt based I2C master write.
		;
		; wait for any ongoing buffered I2C activity to complete
		tstfsz	i2cState			; skip when I2C xfer complete
		goto	$-1					; until then wait
		movlb	4					; select sfr bank for PIE2
		bcf		PIE2, SSPIE			; disable SSP interrupts
		; init i2c out pointer
		movlw	cmdOutBuff - 1		; load prestart of output buffer
		movwf	FSR1				;  into FSR1
		movwf	i2cDataPtr			;  and into master buffer ptr
		movlw	0x0D				; load ascii CR char into W
		clrf	i2cByteCnt			; init byte count
		; loop here to count chars until CR
		incf	FSR1				; inc to next char
		incf	i2cByteCnt			; inc byte count
		cpfseq	INDF1				; skip if current char is CR
		goto	$-3					; otherwise test next char
		; init ssp peripheral to 100KHz i2c master @ 16MHz
		movlb	6					; select sfr bank for ssp
		movlw	0x28				; enable ssp periph and select I2C Master
		movwf	SSPCON1				; in SSPCON1
		movlw	.19					; SSPBRG value for 16MHz and 100KHz
		movwf	SSPADD				; init baud rate generator reload value
		movlw	.19					; load state number for master transmit
		movwf	i2cState			; set I2C state for write start complete
		movlb	4					; select sfr bank for PIE2
		bcf		PIR2, SSPIF			; init interrupt flag
		bsf		PIE2, SSPIE			; enable SSP interrupts
		movlb	6					; select sfr bank for ssp
		bsf		SSPCON2, SEN		; initiate a start sequence
		; the resulting interrupt kicks off the i2c int based state machine
		return						; I2C start initiated, return from Cmd
		;
		;**********************************************************************
I2CIsr	; I2C interrupt service routine
		;**********************************************************************
		;
		; The following macro causes this function to be called from the 
		;  peripheral interrupt vector when the SSPIF flag and SSPIE interrupt
		;  enable are set. This macro must be placed immediately following the 
		;  label at the beginning of the isr function and prior to any 
		;  executable code. 
		;
		;  include bit testing at the peripheral int vector at assembly time
	InstallISR	4, PIR2, SSPIF		; install isr for ssp
		;
		; This function must be terminated by a return to the peripheral isr 
		;  which restores context and performs the retfie. 
		;
		; Each time this function is called it clears the interrupt flag, 
		;  initiates an action that will cause another interrupt to occur,
		;  and then returns. A state machine causes the correct action to be 
		;  initiated during processing of each sequential interrupt.
		;
		; clear interrupt flag
		movlb	4					; select sfr bank for PIE2
		bcf		PIR2, SSPIF			; s/w clear of interrupt flag
		movlb	6					; select sfr bank for ssp
		;
		; The sequence of control for the ssp peripheral, i2c protocol, and 
		;  i2c eeprom device is provided by a software state machine. This 
		;  state machine is implimented as a jump table in which a variable,
		;  i2cState, is added to the current PC. This redirects processor
		;  execution into a block of sequential goto instructions. These goto
		;  instructions jump to the code to be executed for this state of the
		;  sequence  This code can initiate an action that will cause another
		;  ssp interrupt. It also controls the value of i2cState vsriable 
		;  which controls which state code will be executed on the next ssp 
		;  interrupt.
		;
		; define mask that limits the range of value of the state variable
	i2cSizeMask	equ	0x3F		; allow 64 states, must be a power of 2
		; Note: Macro fills jump table to this many instructions preventing
		;       branching beyond the end.
		;
		; ***** Executable code for I2C isr *****
		;
		movlw	high (I2CJump)		; fetch upper byte of jump table address
		movwf	PCLATH				; load into upper PC latch
		movlw	i2cSizeMask			; load number of states
		andwf	i2cState, W			; load the masked state variable into W
		addlw	low (I2CJump) + 1	; calc state machine jump addr into W
		btfsc	ALUSTA, C			; skip if carry occured
		incf	PCLATH				; otherwise add carry
I2CJump	; address were jump table branch occurs, this addr also used in fill 
		movwf	PCL					; index into state machine jump table
		; jump to processing for each state		= i2cState value for each state
		goto	I2CIdle				; i2c idle							= 0
		; I2C master eeprom write state sequence w/ ack polling
		goto	EEWrtStart			; write start sequence completed	= 1
		goto	EEWrtCmd			; ee write command completed		= 2
		goto	EEWrtAddr			; ee memory address out completed	= 3
		goto	EEWrtData			; data out completed				= 4
		goto	EEWrtStop			; stop sequence completed			= 5
		goto	EEWrtBufFull		; eeprom write buffer full			= 6
		goto	EEWrtFullStop		; restart new write					= 7
		goto	EEWrtFullStart		; buff full start sequence complete	= 8
		goto	EEWrtRdCmd			; ack test write command completed	= 9
		; I2C master eeprom read state sequence
		goto	EERdStart			; read start sequence completed		= 10
		goto	EERdWrtCmd			; ee write command completed		= 11
		goto	EERdAddr			; ee memory addr out completed		= 12
		goto	EERdRestart			; restart sequence completed		= 13
		goto	EERdCmd				; ee read command completed			= 14
		goto	EERdData			; data read completed				= 15
		goto	EERdAck				; ack sequence completed		 	= 16
		goto	EERdNack			; nack sequence completed			= 17
		goto	EERdStop			; stop sequence completed			= 18
		; I2C master write state sequence
		goto	MstrWrtStart		; write start sequence completed	= 19
		goto	MstrWrtAddr			; i2c address out completed			= 20
		goto	MstrRpyAddr			; reply address out completed		= 21
		goto	MstrByteCnt			; byte count out completed			= 22
		goto	MstrDataTx			; data buffer out completed			= 23
		; I2C master read state sequence
		goto	MstrRdStart			; read start sequence completed		= 24
		goto	MstrRdAddr			; read address completed			= 25
		goto	MstrRdData			; data read completed				= 26
		goto	MstrRdAck			; ack sequence completed		 	= 27
		goto	MstrRdStop			; stop sequence completed			= 28
		; I2C slave write state sequence
		goto	SlavRpyAddr			; reply address received			= 29
		goto	SlavByteCnt			; byte count received				= 30
		goto	SlavDataRx			; data byte received				= 31
		; I2C slave read state sequence
		goto	SlavDataTx			; read data sequence completed		= 32
		; total range of jump table is set by i2cSizeMask
		; fill with return from here to end of maximum I2CJump table
	Fill (return),  I2CJump + i2cSizeMask - $
		;
I2CIdle								; i2c idle 							= 0
		btfsc	SSPCON1, 3			; skip if not in master mode
		goto	$					; otherwise muti-master error trap
		btfsc	SSPSTAT, D_A		; skip if address was received
		goto	$					; otherwise data error trap
		; i2c slave address match has occurred
		movfp	SSPBUF, WREG		; clear address from SSPBUF
		btfsc	SSPSTAT, R_W		; skip if operation is a write
		goto	SlvRd				; otherwise operation is a read
		movlw	i2cRxBuffer - 1		; load prestart of Rx buffer
		movwf	i2cIntRxPtr			;  into pointer for slave receive
		movlw	.29					; load value for SlavRpyAddr
		movwf	i2cState			;  into i2cState
		return						; return to restore context and exit isr
SlvRd	; slave transmission has been requested
		movlw	i2cSlvRdBuff		; load start of slave read string
		movwf	FSR1				;  into FSR1
		movpf	INDF1, SSPBUF		; load first char for transmission
		bsf		SSPCON1, CKP		; release SCL to allow transfer
		movpf	FSR1, i2cSlvPtr		; save pointer
		movlw	.32					; load value for SlavDataTx
		movwf	i2cState			;  into i2cState
		return						; return to restore context and exit isr
		;
		; ***** I2C master write state sequence *****
		;
EEWrtStart							; write start sequence completed	= 1
		btfsc	SSPCON2, SEN		; skip once SEN is cleared
		goto	$-1					; until then wait
		incf	i2cState			; start complete increment I2C state
		movlw	0xA0				; load I2C addr command for ee write
		movwf	SSPBUF				; output I2C addr command for ee write
		return						; return to restore context and exit isr
		;
EEWrtCmd							; ee write command completed		= 2
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cState			; cmd out complete increment I2C state
		movfp	i2cEEAddr, WREG		; fetch ee memory write addr
		movwf	SSPBUF				; output ee memory write addr
		return						; return to restore context and exit isr
		;
EEWrtAddr		; ee memory address output completed					= 3
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		; start write of data pointed to by i2cDataPtr
		movfp	i2cDataPtr, FSR1	; load buffer pointer into FSR1
		movpf	INDF1, SSPBUF		; output ee memory data parameter
		tstfsz	INDF1				; skip if last output value was zero
		goto	$+3					; otherwise point to next data parameter
		; last data output was 0, terminate write
		incf	i2cState			; output 0 terminated, increment I2C state
		return						; return to restore context and exit isr
		; last data output was not 0, test for ee buffer overflow
		incf	i2cDataPtr			; inc pointer to next data value
		incf	i2cEEAddr			; inc current ee write addr
		movlw	0x07				; load mask for 8 byte ee write buffer
		andwf	i2cEEAddr, W		; mask ee write addr into W
		tstfsz	WREG				; is next addr at start of ee write buffer?
		; if not return w/o changeing i2cState, this code again next int
		return						; return to restore context and exit int
		; otherwise stop and resend ee memory addr before ack polling
		movlw	6					; load numeric value for MstWrtBufFull
		movwf	i2cState			; into MstWrtData, making it the next state
		return						; return to restore context and exit isr
		;
EEWrtData							; data out completed				= 4
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cState			; data out complete increment I2C state
		bsf		SSPCON2, PEN		; initiate a stop sequence
		return						; return to restore context and exit isr
		;
EEWrtStop							; stop sequence completed			= 5
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		call	RstI2C				; reset to i2c slave operation
		return						; return to restore context and exit isr
		;
EEWrtBufFull						; eeprom write buffer full			= 6
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cState			; ee write buffer full inc I2C state 
		bsf		SSPCON2, PEN		; initiate a stop sequence
		return						; return to restore context and exit isr
		;
EEWrtFullStop						; buffer full stop sequence complete= 7
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		incf	i2cState			; buffer full stop complete inc I2C state 
		bsf		SSPCON2, RSEN		; initiate a restart sequence
		return						; return to restore context and exit isr
		;
EEWrtFullStart						; buff full start sequence complete	= 8
		btfsc	SSPCON2, RSEN		; skip once RSEN is cleared
		goto	$-1					; until then wait
		incf	i2cState			; start complete, increment I2C state
		movlw	0xA0				; load command for ee write to test ack
		movwf	SSPBUF				; output I2C addr command for ee write
		return						; return to restore context and exit isr
		;
EEWrtRdCmd							; ack test write command completed	= 9
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		btfss	SSPCON2, ACKSTAT	; skip if no write ack
		goto	$+4					; otherwise ack received, cont write
		decf	i2cState			; no ack, decrement I2C state
		bsf		SSPCON2, RSEN		; initiate a restart sequence
		return						; return to restore context and exit isr
		; ack received, eeprom ready, write eeprom memory address
		movlw	3					; eeprom ready, load I2C state
		movwf	i2cState			; so next state is memory write complete
		movfp	i2cEEAddr, WREG		; fetch ee memory write addr
		movwf	SSPBUF				; output ee memory write addr
		return						; return to restore context and exit isr
		;
		; ***** I2C master read state sequence *****
		;
EERdStart							; read start sequence completed		= 10
		btfsc	SSPCON2, SEN		; skip once SEN is cleared
		goto	$-1					; until then wait
		incf	i2cState			; start complete increment I2C state
		movlw	0xA0				; load I2C addr command for ee write
		movwf	SSPBUF				; output I2C addr command for ee write
		return						; return to restore context and exit isr
		;
EERdWrtCmd							; ee write command out completed	= 11
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cState			; write cmd complete, increment I2C state
		movlw	cmdPrmBuff			; load addr of cmd parameter buffer start
		movwf	FSR1				; into FSR1
		movpf	INDF1, SSPBUF		; output ee memory address parameter
		return						; return to restore context and exit isr
		;
EERdAddr							; ee memory address out completed	= 12
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cState			; ee addr out complete, increment I2C state
		bsf		SSPCON2, RSEN		; initiate a restart condition
		return						; return to restore context and exit isr
		;
EERdRestart							; restart sequence completed		= 13
		btfsc	SSPCON2, RSEN		; skip once RSEN is cleared
		goto	$-1					; until then wait
		incf	i2cState			; restart complete, increment I2C state
		movlw	0xA1				; load I2C addr command for ee read
		movwf	SSPBUF				; output I2C addr command for ee read
		return						; return to restore context and exit isr
		;
EERdCmd								; read command completed			= 14
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cState			; read cmd complete increment I2C state
		movfp	cmdOutPtr, WREG		; load cmd output pointer into W
		incf	WREG				; point to next output buffer location
		movwf	i2cDataPtr			; save it into I2C master pointer
		bsf		SSPCON2, RCEN		; start receiving data byte
		return						; return to restore context and exit isr
		;
EERdData							; data read completed				= 15
		btfsc	SSPCON2, RCEN		; skip once RCEN is cleared
		goto	$-1					; until then wait
		btfss	SSPSTAT, BF			; skip once BF is set
		goto	$-1					; until then wait
		incf	i2cState			; data read complete increment I2C state
		movfp	i2cDataPtr, FSR1	; load buffer pointer into FSR1
		movfp	SSPBUF, INDF1		; copy ee data value into output buffer
		tstfsz	INDF1				; skip if last read value was zero
		goto	EERdNZ				; otherwise jump to test output addr
EERdZ	; last data read was zero, or buffer is full, send nack to end read
		movlw	'\n'				; load LF to replace last char so that
		movwf	INDF1				;  u1: will redraw cmd line prompt
		incf	FSR1				; point to next location
		movlw	'\r'				; load ascii CR into last location in buff
		movwf	INDF1				;  CR terminates cmd line when resubmited
		incf	i2cState			; all data read so inc I2C state again
		bsf		SSPCON2, ACKDT		; set nack to terminate ee read
		bsf		SSPCON2, ACKEN		; start nack sequence
		return						; return to restore context and exit isr
EERdNZ	; last data was not 0, if buffer full jump back to nack
		movlw	cmdOutBuff + cmdOutBuffSize - 2	; load end addr in cmdOutBuff
		cpfslt	i2cDataPtr			; skip if output buffer is not full
		goto	EERdZ				; otherwise buffer is full, send nack
		incf	i2cDataPtr			; inc pointer to next output location
		bcf		SSPCON2, ACKDT		; generate ack to continue ee read
		bsf		SSPCON2, ACKEN		; start ack sequence
		return						; return to restore context and exit isr
		;
EERdAck								; ack sequence completed			= 16
		btfsc	SSPCON2, ACKEN		; skip once ACKEN is cleared
		goto	$-1					; until then wait
		decf	i2cState			; ack complete decrement I2C state
		bsf		SSPCON2, RCEN		; start receiving data byte
		return						; return to restore context and exit isr
		;
EERdNack							; nack sequence completed			= 17
		btfsc	SSPCON2, ACKEN		; skip once ACKEN is cleared
		goto	$-1					; until then wait
		incf	i2cState			; nack complete increment I2C state
		bsf		SSPCON2, PEN		; initiate a stop sequence
		return						; return to restore context and exit isr
		;
EERdStop							; stop sequence completed			= 18
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		call	RstI2C				; reset to i2c slave operation
		return						; return to restore context and exit isr
		;
		; ***** I2C master write state sequence *****
		;
MstrWrtStart						; write start sequence completed	= 19
		btfsc	SSPCON2, SEN		; skip once SEN is cleared
		goto	$-1					; until then wait
		incf	i2cState			; start complete increment I2C state
		movfp	i2cAddr, WREG		; load I2C addr
		movwf	SSPBUF				; output I2C addr command for ee write
		return						; return to restore context and exit isr
		;
MstrWrtAddr							; i2c address out completed			= 20
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		movfp	i2cAddr, WREG		; move the acknowledged i2c addr
		movwf	i2cRpyPend			;  into the pending reply gpr
		incf	i2cState			; data out complete, increment I2C state
		movfp	i2cSlvAddr, WREG	; load local slave address for reply
		movwf	SSPBUF				; output I2C addr command for ee write
		return						; return to restore context and exit isr
		;
MstrRpyAddr							; reply address out completed		= 21
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cState			; reply out complete, increment I2C state
		movfp	i2cByteCnt, WREG	; load byte count
		movwf	SSPBUF				; output I2C addr command for ee write
		return						; return to restore context and exit isr
		;
MstrByteCnt							; byte count out completed			= 22
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cDataPtr			; point to new data location
		movfp	i2cDataPtr, FSR1	; load output buffer pointer into FSR1
		movpf	INDF1, SSPBUF		; put data value into buffer
		decfsz	i2cByteCnt			; decrement byte count and skip if 0
		return						; otherwise return to restore and exit isr
		incf	i2cState			; data out complete, increment I2C state
		bsf		SSPCON2, PEN		; initiate a stop sequence
		return						; return to restore context and exit isr
		;
MstrDataTx							; data buffer out completed			= 23
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		call	RstI2C				; reset to i2c slave operation
		return						; return to restore context and exit isr
		;
		; ***** I2C master read state sequence *****
		;
MstrRdStart							; read start sequence completed		= 24
		btfsc	SSPCON2, SEN		; skip once SEN is cleared
		goto	$-1					; until then wait
		incf	i2cState			; start complete, increment I2C state
		movlw	cmdPrmBuff			; load addr of cmd parameter buffer start
		movwf	FSR1				; into FSR
		movpf	INDF1, WREG			; fetch i2c address parameter into W
		rlncf	WREG				; shift i2c addr out of lsb
		bsf		WREG, 0				; set lsb for read
		movwf	SSPBUF				; output addr / command for i2c read
		return						; return to restore context and exit isr
		;
MstrRdAddr							; i2c address out completed			= 25
		btfsc	SSPSTAT, R_W		; skip once R/W is cleared
		goto	$-1					; until then wait
		incf	i2cState			; i2c addr out complete, increment state
		movfp	cmdOutPtr, WREG		; load cmd output pointer into W
		incf	WREG				; point to next location, keeping \n
		movwf	i2cDataPtr			; save it into I2C master pointer
		bsf		SSPCON2, RCEN		; start receiving data byte
		return						; return to restore context and exit isr
		;
MstrRdData							; data read completed				= 26
		btfsc	SSPCON2, RCEN		; skip once RCEN is cleared
		goto	$-1					; until then wait
		btfss	SSPSTAT, BF			; skip once BF is set
		goto	$-1					; until then wait
		incf	i2cState			; data read complete increment I2C state
		movfp	i2cDataPtr, FSR1	; load buffer pointer into FSR1
		movfp	SSPBUF, INDF1		; copy ee data value into output buffer
		tstfsz	INDF1				; skip if last read value was zero
		goto	MstrRdNZ			; otherwise jump to test output addr
MstrRdZ	; last data read was zero, or buffer is full, send nack to end read
		movlw	'\n'				; load LF to replace last char so that
		movwf	INDF1				;  u1: will redraw cmd line prompt
		incf	FSR1				; point to next location
		movlw	'\r'				; load ascii CR into last location in buff
		movwf	INDF1				;  CR terminates cmd line when resubmited
		incf	i2cState			; all data read so inc I2C state again
		bsf		SSPCON2, ACKDT		; set nack to terminate ee read
		bsf		SSPCON2, ACKEN		; start nack sequence
		return						; return to restore context and exit isr
MstrRdNZ	; last data was not 0, if buffer full jump back to nack
		movlw	cmdOutBuff + cmdOutBuffSize - 2	; load end addr in cmdOutBuff
		cpfslt	i2cDataPtr			; skip if output buffer is not full
		goto	MstrRdZ				; otherwise buffer is full, send nack
		incf	i2cDataPtr			; inc pointer to next output location
		bcf		SSPCON2, ACKDT		; generate ack to continue ee read
		bsf		SSPCON2, ACKEN		; start ack sequence
		return						; return to restore context and exit isr
		;
MstrRdAck							; ack sequence completed			= 27
		btfsc	SSPCON2, ACKEN		; skip once ACKEN is cleared
		goto	$-1					; until then wait
		decf	i2cState			; ack complete decrement I2C state
		bsf		SSPCON2, RCEN		; start receiving data byte
		return						; return to restore context and exit isr
		;
MstrRdStop							; stop sequence completed			= 28
		btfsc	SSPCON2, PEN		; skip once PEN is cleared
		goto	$-1					; until then wait
		call	RstI2C				; reset to i2c slave operation
		return						; return to restore context and exit isr
		;
		; ***** I2C slave write state sequence *****
		;
SlavRpyAddr							; reply address received			= 29
		movfp	SSPBUF, WREG		; receive reply addr into W
		movwf	i2cAddr				; store it in gpr
		incf	i2cState			; inc i2c state to receive byte count
		return						; return to restore context and exit isr
		;
SlavByteCnt							; byte count received				= 30
		movfp	SSPBUF, WREG		; receive byte count into W
		movwf	i2cByteCnt			; store it in gpr
		incf	i2cState			; inc i2c state to receive data
		return						; return to restore context and exit isr
		;
SlavDataRx							; data byte received				= 31
		incf	i2cIntRxPtr			; point to new data location
		movfp	i2cIntRxPtr, FSR1	; load slave write buffer pointer into FSR1
		movfp	SSPBUF, INDF1		; receive data value into buffer
		decfsz	i2cByteCnt			; decrement byte count and skip if 0
		return						; otherwise return to restore and exit isr
		bsf		i2cFlags, i2cRxRdy	; set flag indicating buffer is ready
		clrf	i2cState			; reset i2c state to idle
		return						; return to restore context and exit isr
		;
		; ***** I2C slave read state sequence *****
		;
SlavDataTx							; read data sequence completed		= 32
		btfss	SSPSTAT, R_W		; skip when ACK is sent
		goto	SlvNACK				; otherwise nack was received
		incf	i2cSlvPtr			; point to next char in read buffer
		movfp	i2cSlvPtr, FSR1		; load data read pointer into FSR1
		movpf	INDF1, SSPBUF		; load char for transmission
		bsf		SSPCON1, CKP		; release SCL to allow transfer
		return						; otherwise return to restore and exit isr
SlvNACK	; negative acknowledge has been sent, read is complete
		clrf	i2cState			; reset i2c state to idle
		return						; return to restore context and exit isr

;	movlb	1					; select portd bank
;	btg		PORTD, 7			; toggle debug bit
;	movlb	6					; select ssp bank

;	movfp	SSPSTAT, WREG		; fetch SSPSTAT into W
;	movlb	1					; select portd bank
;	movwf	PORTD				; display SSPSTAT on debug LEDs
;	movlb	6					; select ssp bank

; end of file i2ccmd.asm ******************************************************



file: /Techref/piclist/andrewspicos/i2ccmd.htm, 53KB, , updated: 2002/11/29 00:26, local time: 2024/11/8 15:02,
TOP NEW HELP FIND: 
18.226.88.141:LOG IN
©2024 PLEASE DON'T RIP! THIS SITE CLOSES OCT 28, 2024 SO LONG AND THANKS FOR ALL THE FISH!

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://www.piclist.com/tecHREF/piclist/andrewspicos/i2ccmd.htm"> piclist andrewspicos i2ccmd</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

  PICList 2024 contributors:
o List host: MIT, Site host massmind.org, Top posters @none found
- Page Editors: James Newton, David Cary, and YOU!
* Roman Black of Black Robotics donates from sales of Linistep stepper controller kits.
* Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters.
* Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated!
* Contributors: Richard Seriani, Sr.
 
Quick, Easy and CHEAP! RCL-1 RS232 Level Converter in a DB9 backshell
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .