; i2c.inc ; ; Copyright (C) 2006,2007 Nuno Sucena Almeida ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ; #define SDA_IO TRISB,1 #define SCL_IO TRISB,4 #define ACK 0 #define i2c_ACK i2c_status,ACK ; this bit if set to '0' dictates that the master will send ; an ACK bit, or a NACK otherwise. #define SEND_ACK 1 #define i2c_SEND_ACK i2c_status,SEND_ACK ;; we only allow this many errors,ie ;; data without receiving ACK #define I2C_RETRIES D'10' ;-------------------------------------------------------------------- ; macros to manipulate the i2c ports ; ;-------------------------------------------------------------------- i2c_delay macro call delay10 ; call i2c_debug endm ;-------------------------------------------------------------------- sda_HIGH macro banksel TRISB bsf SDA_IO i2c_delay endm ;-------------------------------------------------------------------- sda_LOW macro banksel TRISB bcf SDA_IO i2c_delay endm ;-------------------------------------------------------------------- scl_HIGH macro banksel TRISB bsf SCL_IO i2c_delay endm ;-------------------------------------------------------------------- scl_LOW macro banksel TRISB bcf SCL_IO i2c_delay endm ;-------------------------------------------------------------------- trigger macro banksel PORTA bsf PORTA,0 banksel PORTA bcf PORTA,0 endm ;-------------------------------------------------------------------- ; I2C start macro, see page 9 of Philips I2C specification i2c_START macro trigger scl_LOW sda_HIGH scl_HIGH i2c_delay sda_LOW i2c_delay scl_LOW i2c_delay endm ;-------------------------------------------------------------------- ; I2C stop macro, see page 9 of Philips I2C specification i2c_STOP macro scl_LOW sda_LOW i2c_delay scl_HIGH i2c_delay sda_HIGH i2c_delay ; scl_LOW ; i2c_delay endm ;-------------------------------------------------------------------- ; this macro waits for the clock line to go HIGH,ie,for the clock ; line to be free. i2c_SCL_WAIT macro local i2c_SCL_WAIT_loop banksel PORTB i2c_SCL_WAIT_loop: btfss SCL_IO goto i2c_SCL_WAIT_loop endm ;-------------------------------------------------------------------- ; this macro reads the i2c data port and puts the result in the Carry ; STATUS bit i2c_READ macro bcf STATUS,C banksel PORTB btfsc SDA_IO bsf STATUS,C endm ;-------------------------------------------------------------------- ; this macro checks the i2c ACK bit and sets the i2c ACK status bit ; accordingly i2c_READ_ACK macro ; set clock to LOW and data to HIGH so that we can check ; the ACK bit scl_LOW sda_HIGH ; set clock HIGH so that we read ACK scl_HIGH ; read ACK bit and set ACK flag accordingly: ; if ACK then SDA is LOW,else HIGH i2c_READ ;set output ACK flag: i2c_ACK_LOW btfsc STATUS,C bsf i2c_ACK ; set clock HIGH scl_HIGH endm ;-------------------------------------------------------------------- ; this macro checks the i2c ACK status and if there's an error ; ie, the bit value is 1, then jumps to the provided 'jumpto' ; else continues. i2c_CHECK_ACK macro jumpto banksel i2c_status btfsc i2c_ACK goto jumpto endm ;-------------------------------------------------------------------- ; this macro sends the ACK bit sequence to the bus ; if the SEND_ACK i2c status bit is '0', or sends the NACK ; if it's set to '1' i2c_WRITE_ACK macro local i2c_WRITE_ACK_Yes local i2c_WRITE_ACK_End ; Clock Line Low scl_LOW banksel i2c_status ; check if the SEND_ACK status bit is '0' ; if yes, then send the ACK bit, NACK otherwise btfss i2c_SEND_ACK goto i2c_WRITE_ACK_Yes ; send NACK sda_HIGH goto i2c_WRITE_ACK_End i2c_WRITE_ACK_Yes: ; send ACK sda_LOW i2c_WRITE_ACK_End: scl_HIGH scl_LOW endm ;-------------------------------------------------------------------- ; The following macros manipulate the i2c status register ;-------------------------------------------------------------------- i2c_ACK_LOW macro banksel i2c_status bcf i2c_ACK endm i2c_ACK_HIGH macro banksel i2c_status bsf i2c_ACK endm i2c_SET_SEND_ACK macro banksel i2c_status bcf i2c_SEND_ACK endm i2c_SET_SEND_NACK macro banksel i2c_status bsf i2c_SEND_ACK endm