; ;********************************************************************** ; 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,
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? <A HREF="http://www.piclist.com/tecHREF/piclist/andrewspicos/i2ccmd.htm"> piclist andrewspicos i2ccmd</A> |
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. |
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! |
.