| 151 | kaklik | 1 | /*
 | 
        
           |  |  | 2 |     Copyright (C) 2004    John Orlando
 | 
        
           |  |  | 3 |   | 
        
           |  |  | 4 |    AVRcam: a small real-time image processing engine.
 | 
        
           |  |  | 5 |   | 
        
           |  |  | 6 |     This program is free software; you can redistribute it and/or
 | 
        
           |  |  | 7 |     modify it under the terms of the GNU General Public
 | 
        
           |  |  | 8 |     License as published by the Free Software Foundation; either
 | 
        
           |  |  | 9 |     version 2 of the License, or (at your option) any later version.
 | 
        
           |  |  | 10 |   | 
        
           |  |  | 11 |     This program is distributed in the hope that it will be useful,
 | 
        
           |  |  | 12 |     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 13 |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
        
           |  |  | 14 |     General Public License for more details.
 | 
        
           |  |  | 15 |   | 
        
           |  |  | 16 |     You should have received a copy of the GNU General Public
 | 
        
           |  |  | 17 |     License along with this program; if not, write to the Free Software
 | 
        
           |  |  | 18 |     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
        
           |  |  | 19 |   | 
        
           |  |  | 20 |    For more information on the AVRcam, please contact:
 | 
        
           |  |  | 21 |   | 
        
           |  |  | 22 |    john@jrobot.net
 | 
        
           |  |  | 23 |   | 
        
           |  |  | 24 |    or go to www.jrobot.net for more details regarding the system.
 | 
        
           |  |  | 25 | */
 | 
        
           |  |  | 26 | /***********************************************************
 | 
        
           |  |  | 27 | 	Module Name: I2CInterface.c
 | 
        
           |  |  | 28 | 	Module Date: 4/10/2004
 | 
        
           |  |  | 29 | 	Module Auth: John Orlando
 | 
        
           |  |  | 30 |   | 
        
           |  |  | 31 | 	Description: This module is responsible for providing a
 | 
        
           |  |  | 32 | 	low-level interface to the I2C hardware resident on the
 | 
        
           |  |  | 33 | 	mega8 processor (also known as the Two-Wire Interface,
 | 
        
           |  |  | 34 | 	or TWI).  The interface is needed to configure the
 | 
        
           |  |  | 35 | 	needed registers in the OV6620 camera.  This interface
 | 
        
           |  |  | 36 | 	is interrupt-driven based on the events that should
 | 
        
           |  |  | 37 | 	occur upon successful writing of an I2C register.
 | 
        
           |  |  | 38 |   | 
        
           |  |  | 39 |     Revision History:
 | 
        
           |  |  | 40 |     Date        Rel Ver.    Notes
 | 
        
           |  |  | 41 |     4/10/2004      0.1     Module created
 | 
        
           |  |  | 42 |     6/30/2004      1.0     Initial release for Circuit Cellar
 | 
        
           |  |  | 43 |                            contest.
 | 
        
           |  |  | 44 |   | 
        
           |  |  | 45 | ***********************************************************/
 | 
        
           |  |  | 46 |   | 
        
           |  |  | 47 | /*	Includes */
 | 
        
           |  |  | 48 | #include <avr/io.h>
 | 
        
           | 174 | kaklik | 49 | #include <util/twi.h>
 | 
        
           | 151 | kaklik | 50 | #include <avr/interrupt.h>
 | 
        
           |  |  | 51 | #include "CamConfig.h"
 | 
        
           |  |  | 52 | #include "CommonDefs.h"
 | 
        
           |  |  | 53 |   | 
        
           |  |  | 54 | /*  Local Variables */
 | 
        
           |  |  | 55 |   | 
        
           |  |  | 56 | /* These variables are used as storage space for the current
 | 
        
           |  |  | 57 |    I2C command being sent over the interface.  They need to
 | 
        
           |  |  | 58 |    be volatile since they are dealt with an the TWI ISR */
 | 
        
           |  |  | 59 | volatile static unsigned char twi_address;
 | 
        
           |  |  | 60 | volatile static unsigned char *twi_data;
 | 
        
           |  |  | 61 | volatile static unsigned char twi_ddr;
 | 
        
           |  |  | 62 | volatile static unsigned char twi_bytes;
 | 
        
           |  |  | 63 | volatile static unsigned char status;
 | 
        
           |  |  | 64 | volatile static unsigned char retry_cnt;
 | 
        
           |  |  | 65 |   | 
        
           |  |  | 66 | /* 	Local Structures and Typedefs */
 | 
        
           |  |  | 67 |   | 
        
           |  |  | 68 | /*  Extern Variables */
 | 
        
           |  |  | 69 |   | 
        
           |  |  | 70 | /*  Definitions */
 | 
        
           |  |  | 71 | /* Bit definitions for the tw_status register */
 | 
        
           |  |  | 72 | #define MAX_TWI_RETRIES 2
 | 
        
           |  |  | 73 | #define BUSY 7
 | 
        
           |  |  | 74 |   | 
        
           |  |  | 75 | /***********************************************************
 | 
        
           |  |  | 76 | 	Function Name: I2CInt_init
 | 
        
           |  |  | 77 | 	Function Description: This function is responsible
 | 
        
           |  |  | 78 | 	for setting up the registers needed for the TWI 
 | 
        
           |  |  | 79 | 	interface
 | 
        
           |  |  | 80 |   | 
        
           |  |  | 81 | 	Inputs:  none
 | 
        
           |  |  | 82 | 	Outputs: none
 | 
        
           |  |  | 83 | ***********************************************************/	
 | 
        
           |  |  | 84 | void I2CInt_init(void)
 | 
        
           |  |  | 85 | {
 | 
        
           |  |  | 86 | 	TWSR = 0;
 | 
        
           |  |  | 87 |   | 
        
           |  |  | 88 | 	/* init the speed of the I2C interface, running at
 | 
        
           |  |  | 89 |     100 Kbps */
 | 
        
           |  |  | 90 | 	TWBR = (FOSC / I2C_SPEED - 16)/2;
 | 
        
           |  |  | 91 | }
 | 
        
           |  |  | 92 |   | 
        
           |  |  | 93 | /***********************************************************
 | 
        
           |  |  | 94 | 	Function Name: I2CInt_writeData
 | 
        
           |  |  | 95 | 	Function Description: This function is responsible for
 | 
        
           |  |  | 96 | 	initiating the process of writing a sequence of bytes
 | 
        
           |  |  | 97 | 	an I2C slave address.  This function will try to write
 | 
        
           |  |  | 98 | 	the data three times before giving up.
 | 
        
           |  |  | 99 | 	Inputs: address: the address of the I2C slave device
 | 
        
           |  |  | 100 | 			data: a pointer to the data to be written 
 | 
        
           |  |  | 101 | 				  to the slave...for camera interfacing,
 | 
        
           |  |  | 102 | 				  the data follows a <register #><data>
 | 
        
           |  |  | 103 | 				  format
 | 
        
           |  |  | 104 | 			bytes: the number of bytes to write 
 | 
        
           |  |  | 105 | 	Outputs: none
 | 
        
           |  |  | 106 | ***********************************************************/
 | 
        
           |  |  | 107 | void I2CInt_writeData(unsigned char address, unsigned char *data, unsigned char bytes)
 | 
        
           |  |  | 108 | {
 | 
        
           |  |  | 109 | 	while(status & (1<<BUSY));		/* Bus is busy wait (or exit with error code) */
 | 
        
           |  |  | 110 | 	while(TWCR & (1<<TWSTO));
 | 
        
           |  |  | 111 |   | 
        
           |  |  | 112 | 	/* copy the needed data and state info to our local I2C command structure */
 | 
        
           |  |  | 113 | 	twi_address = address;
 | 
        
           |  |  | 114 | 	twi_data = data;
 | 
        
           |  |  | 115 | 	twi_bytes = bytes;
 | 
        
           |  |  | 116 | 	twi_ddr = TW_WRITE;
 | 
        
           |  |  | 117 |   | 
        
           |  |  | 118 | 	retry_cnt = 0;
 | 
        
           |  |  | 119 |   | 
        
           |  |  | 120 | 	/* Generate start condition, the remainder of the transfer is interrupt driven and
 | 
        
           |  |  | 121 | 	   will be performed in the background */
 | 
        
           |  |  | 122 | 	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);
 | 
        
           |  |  | 123 |   | 
        
           |  |  | 124 | 	status |= (1<<BUSY);
 | 
        
           |  |  | 125 | }
 | 
        
           |  |  | 126 |   | 
        
           |  |  | 127 | /***********************************************************
 | 
        
           |  |  | 128 | 	Function Name: I2CInt_readData
 | 
        
           |  |  | 129 | 	Function Description: This funcion is responsible for
 | 
        
           |  |  | 130 | 	reading the specified number of bytes from a slave
 | 
        
           |  |  | 131 | 	device.
 | 
        
           |  |  | 132 | 	Inputs:  address: the slave address to read from
 | 
        
           |  |  | 133 | 			 data: a pointer to where the data will be stored
 | 
        
           |  |  | 134 | 			 bytes: the number of bytes to read
 | 
        
           |  |  | 135 | 	Outputs: none
 | 
        
           |  |  | 136 | ***********************************************************/
 | 
        
           |  |  | 137 | void I2CInt_readData(unsigned char address, unsigned char *data, unsigned char bytes)
 | 
        
           |  |  | 138 | {
 | 
        
           |  |  | 139 |     /* Bus is busy wait (or exit with error code) */
 | 
        
           |  |  | 140 | 	while(status & (1<<BUSY));									
 | 
        
           |  |  | 141 |   | 
        
           |  |  | 142 | 	twi_address = address;
 | 
        
           |  |  | 143 | 	twi_data = data;
 | 
        
           |  |  | 144 | 	twi_bytes = bytes;
 | 
        
           |  |  | 145 | 	twi_ddr = TW_READ;
 | 
        
           |  |  | 146 |   | 
        
           |  |  | 147 | 	retry_cnt = 0;
 | 
        
           |  |  | 148 |   | 
        
           |  |  | 149 | 	/* Generate start condition, the remainder of the transfer is interrupt driven and
 | 
        
           |  |  | 150 | 	   will be performed in the background */
 | 
        
           |  |  | 151 | 	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);
 | 
        
           |  |  | 152 |   | 
        
           |  |  | 153 | 	status |= (1<<BUSY);
 | 
        
           |  |  | 154 | }
 | 
        
           |  |  | 155 |   | 
        
           |  |  | 156 | /***********************************************************
 | 
        
           |  |  | 157 | 	Function Name: I2CInt_isI2cBusy
 | 
        
           |  |  | 158 | 	Function Description: This funcion is responsible for
 | 
        
           |  |  | 159 | 	indicating if the I2C bus is currently busy to external
 | 
        
           |  |  | 160 | 	modules.
 | 
        
           |  |  | 161 | 	device.
 | 
        
           |  |  | 162 | 	Inputs:  none
 | 
        
           |  |  | 163 | 	Outputs: bool_t - indicating if bus is busy
 | 
        
           |  |  | 164 | ***********************************************************/
 | 
        
           |  |  | 165 | bool_t I2CInt_isI2cBusy(void)
 | 
        
           |  |  | 166 | {
 | 
        
           |  |  | 167 | 	bool_t retVal = FALSE;
 | 
        
           |  |  | 168 | 	if ( (status & (1<<BUSY)) != 0)
 | 
        
           |  |  | 169 | 	{
 | 
        
           |  |  | 170 | 		retVal = TRUE;
 | 
        
           |  |  | 171 | 	}
 | 
        
           |  |  | 172 |   | 
        
           |  |  | 173 | 	return(retVal);
 | 
        
           |  |  | 174 | }
 | 
        
           |  |  | 175 |   | 
        
           |  |  | 176 | /***********************************************************
 | 
        
           |  |  | 177 | 	Function Name: <interrupt handler for I2C>
 | 
        
           |  |  | 178 | 	Function Description: This function is responsible for
 | 
        
           |  |  | 179 | 	implementing the control logic needed to perform a
 | 
        
           |  |  | 180 | 	read or write operation with an I2C slave.
 | 
        
           |  |  | 181 | 	Inputs:  none
 | 
        
           |  |  | 182 | 	Outputs: none
 | 
        
           |  |  | 183 | ***********************************************************/
 | 
        
           |  |  | 184 | SIGNAL(SIG_2WIRE_SERIAL)
 | 
        
           |  |  | 185 | {
 | 
        
           |  |  | 186 | 	unsigned char TWI_status = TWSR & TW_STATUS_MASK;   /* grab just the status bits */
 | 
        
           |  |  | 187 |   | 
        
           |  |  | 188 |     /* the entire I2C handler is state-based...determine
 | 
        
           |  |  | 189 |     what needs to be done based on TWI_status */
 | 
        
           |  |  | 190 | 	switch(TWI_status) 
 | 
        
           |  |  | 191 |     {
 | 
        
           |  |  | 192 |         case TW_START:									/* Start condition */
 | 
        
           |  |  | 193 |         case TW_REP_START:								/* Repeated start condition */
 | 
        
           |  |  | 194 |             if(retry_cnt > MAX_TWI_RETRIES) 
 | 
        
           |  |  | 195 |             {
 | 
        
           |  |  | 196 |                 /* generate stop condition if we've reached our retry limit */
 | 
        
           |  |  | 197 |                 TWCR |= (1<<TWINT)|(1<<TWSTO);					
 | 
        
           |  |  | 198 |                 status &= ~(1<<BUSY);								
 | 
        
           |  |  | 199 |                 return;												
 | 
        
           |  |  | 200 |             }
 | 
        
           |  |  | 201 |             /* indicate read or write */
 | 
        
           |  |  | 202 |             TWDR = (twi_address<<1) + twi_ddr;	
 | 
        
           |  |  | 203 |             /* TWSTA must be cleared...also clears TWINT */
 | 
        
           |  |  | 204 |             TWCR &= ~(1<<TWSTA);
 | 
        
           |  |  | 205 |             break;
 | 
        
           |  |  | 206 |   | 
        
           |  |  | 207 |         case TW_MT_SLA_ACK:							/* Slave acknowledged address, */
 | 
        
           |  |  | 208 |             retry_cnt = 0;					
 | 
        
           |  |  | 209 |             /* tx the data, and increment the data pointer */
 | 
        
           |  |  | 210 |             TWDR = *twi_data;										
 | 
        
           |  |  | 211 |             twi_data++;			
 | 
        
           |  |  | 212 |   | 
        
           |  |  | 213 |             /* clear the int to continue */
 | 
        
           |  |  | 214 |             TWCR |= (1<<TWINT);						
 | 
        
           |  |  | 215 |             break;
 | 
        
           |  |  | 216 |   | 
        
           |  |  | 217 |         case TW_MT_SLA_NACK:							/* Slave didn't acknowledge address, */
 | 
        
           |  |  | 218 |         case TW_MR_SLA_NACK:
 | 
        
           |  |  | 219 |             retry_cnt++;		
 | 
        
           |  |  | 220 |   | 
        
           |  |  | 221 |             /* retry...*/
 | 
        
           |  |  | 222 |             TWCR |= (1<<TWINT)|(1<<TWSTA)|(1<<TWSTO);	
 | 
        
           |  |  | 223 |             break;
 | 
        
           |  |  | 224 |   | 
        
           |  |  | 225 |         case TW_MT_DATA_ACK:							/* Slave Acknowledged data, */
 | 
        
           |  |  | 226 |             if(--twi_bytes > 0) 
 | 
        
           |  |  | 227 |             {						
 | 
        
           |  |  | 228 |                 /* more data to send, so send it */
 | 
        
           |  |  | 229 |                 TWDR = *twi_data;									
 | 
        
           |  |  | 230 |                 twi_data++;											
 | 
        
           |  |  | 231 |                 TWCR |= (1<<TWINT);								
 | 
        
           |  |  | 232 |             }
 | 
        
           |  |  | 233 |             else 
 | 
        
           |  |  | 234 |             {
 | 
        
           |  |  | 235 |                 /* generate the stop condition if needed */
 | 
        
           |  |  | 236 |                 TWCR |= (1<<TWSTO)|(1<<TWINT);					
 | 
        
           |  |  | 237 |                 status &= ~(1<<BUSY);								
 | 
        
           |  |  | 238 |             }
 | 
        
           |  |  | 239 |             break;
 | 
        
           |  |  | 240 |   | 
        
           |  |  | 241 |         case TW_MT_DATA_NACK:							/* Slave didn't acknowledge data */
 | 
        
           |  |  | 242 |             /* send the stop condition */
 | 
        
           |  |  | 243 |             TWCR |= (1<<TWINT)|(1<<TWSTO);						
 | 
        
           |  |  | 244 |             status &= ~(1<<BUSY);									
 | 
        
           |  |  | 245 |             break;
 | 
        
           |  |  | 246 |   | 
        
           |  |  | 247 |         case TW_MR_SLA_ACK:                             /* Slave acknowledged address */
 | 
        
           |  |  | 248 |             if(--twi_bytes > 0) 
 | 
        
           |  |  | 249 |             {
 | 
        
           |  |  | 250 |                 /* if there is more than one byte to read, acknowledge */
 | 
        
           |  |  | 251 |                 TWCR |= (1<<TWEA)|(1<<TWINT);	
 | 
        
           |  |  | 252 |             }
 | 
        
           |  |  | 253 | 			else
 | 
        
           |  |  | 254 |             {
 | 
        
           |  |  | 255 |                 /* no acknowledge */
 | 
        
           |  |  | 256 |                 TWCR |= (1<<TWINT);					
 | 
        
           |  |  | 257 |             }
 | 
        
           |  |  | 258 |             break;
 | 
        
           |  |  | 259 |   | 
        
           |  |  | 260 |         case TW_MR_DATA_ACK: 							/* Master acknowledged data */
 | 
        
           |  |  | 261 |   | 
        
           |  |  | 262 |             /* grab the received data */
 | 
        
           |  |  | 263 |             *twi_data = TWDR;										
 | 
        
           |  |  | 264 |             twi_data++;											
 | 
        
           |  |  | 265 |             if(--twi_bytes > 0) 
 | 
        
           |  |  | 266 |             {
 | 
        
           |  |  | 267 |                 /* get the next data byte and ack */
 | 
        
           |  |  | 268 |                 TWCR |= (1<<TWEA)|(1<<TWINT);	
 | 
        
           |  |  | 269 |             }
 | 
        
           |  |  | 270 |             else
 | 
        
           |  |  | 271 |             {
 | 
        
           |  |  | 272 |                 /* clear out the enable acknowledge bit */
 | 
        
           |  |  | 273 |                 TWCR &= ~(1<<TWEA);							
 | 
        
           |  |  | 274 |             }
 | 
        
           |  |  | 275 |             break;
 | 
        
           |  |  | 276 |   | 
        
           |  |  | 277 |         case TW_MR_DATA_NACK:						/* Master didn't acknowledge data -> end of read process */
 | 
        
           |  |  | 278 |             /* read data, and generate the stop condition */
 | 
        
           |  |  | 279 |             *twi_data = TWDR;										
 | 
        
           |  |  | 280 |             TWCR |= (1<<TWSTO)|(1<<TWINT); 						
 | 
        
           |  |  | 281 |             status &= ~(1<<BUSY);											
 | 
        
           |  |  | 282 |             break;
 | 
        
           |  |  | 283 | 	}
 | 
        
           |  |  | 284 | }
 | 
        
           |  |  | 285 |   | 
        
           |  |  | 286 |   | 
        
           |  |  | 287 |   | 
        
           |  |  | 288 |   | 
        
           |  |  | 289 |   | 
        
           |  |  | 290 |   | 
        
           |  |  | 291 |   | 
        
           |  |  | 292 |   | 
        
           |  |  | 293 |   |