> [snip lot of text about using bsf and bsf for twiddling SDA and SCL] No, it really is okay to use bsf and bcf to twiddle SDA and SCL. I do. I twiddle the bits in the TRIS registers. AFAIK this does not disturb other bits in the register, or I/O bits. So I2C events do not disturb other I/O bits. The disturbances discussed previously only happen if you twiddle the PORT register bits. Which you should not be doing, because the I2C signals are open collector! You should be twiddling the TRIS bits, and keeping the corresponding PORT bits low. You have to avoid other I/O bits disturbing the I2C PORT bits. BTW, the last chap's I2C file looks flaky for a start. Look at the code: > SendI2CStart > movlw ~(SDA_MASK|SCL_MASK) ; make sure output > ; lines are low > andwf I2CPORT ; when outputs are enabled There's nothing to guarantee the timing. The I2C spec says the start condition is SCL falling when SDA is low. AND the time between SDA falling and SCL falling must be at least 4 microseconds! I use something like this: I2C_SCL_HI MACRO bsf TRISC, I2C_SCL ; Set SCL high ENDM I2C_SCL_LO MACRO bcf TRISC, I2C_SCL ; Set SCL low ENDM I2C_SDA_HI MACRO bsf TRISC, I2C_SDA ; Set SDA high ENDM I2C_SDA_LO MACRO bcf TRISC, I2C_SDA ; Set SDA low ENDM doWait3microseconds MACRO nop nop nop ENDM So that you do a START like so: page1 ; meaning data page I2C_SDA_LO ; SDA goes low during SCL high doWait3microseconds ; I2C_SCL_LO ; Start clock train page0 ; return with data page == 0