Rev 151 | Blame | Last modification | View Log | Download
/*Copyright (C) 2004 John OrlandoAVRcam: a small real-time image processing engine.This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General PublicLicense as published by the Free Software Foundation; eitherversion 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General PublicLicense along with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USAFor more information on the AVRcam, please contact:john@jrobot.netor go to www.jrobot.net for more details regarding the system.*//***********************************************************Module Name: I2CInterface.cModule Date: 4/10/2004Module Auth: John OrlandoDescription: This module is responsible for providing alow-level interface to the I2C hardware resident on themega8 processor (also known as the Two-Wire Interface,or TWI). The interface is needed to configure theneeded registers in the OV6620 camera. This interfaceis interrupt-driven based on the events that shouldoccur upon successful writing of an I2C register.Revision History:Date Rel Ver. Notes4/10/2004 0.1 Module created6/30/2004 1.0 Initial release for Circuit Cellarcontest.***********************************************************//* Includes */#include <avr/io.h>#include <util/twi.h>#include <avr/interrupt.h>#include "CamConfig.h"#include "CommonDefs.h"/* Local Variables *//* These variables are used as storage space for the currentI2C command being sent over the interface. They need tobe volatile since they are dealt with an the TWI ISR */volatile static unsigned char twi_address;volatile static unsigned char *twi_data;volatile static unsigned char twi_ddr;volatile static unsigned char twi_bytes;volatile static unsigned char status;volatile static unsigned char retry_cnt;/* Local Structures and Typedefs *//* Extern Variables *//* Definitions *//* Bit definitions for the tw_status register */#define MAX_TWI_RETRIES 2#define BUSY 7/***********************************************************Function Name: I2CInt_initFunction Description: This function is responsiblefor setting up the registers needed for the TWIinterfaceInputs: noneOutputs: none***********************************************************/void I2CInt_init(void){TWSR = 0;/* init the speed of the I2C interface, running at100 Kbps */TWBR = (FOSC / I2C_SPEED - 16)/2;}/***********************************************************Function Name: I2CInt_writeDataFunction Description: This function is responsible forinitiating the process of writing a sequence of bytesan I2C slave address. This function will try to writethe data three times before giving up.Inputs: address: the address of the I2C slave devicedata: a pointer to the data to be writtento the slave...for camera interfacing,the data follows a <register #><data>formatbytes: the number of bytes to writeOutputs: none***********************************************************/void I2CInt_writeData(unsigned char address, unsigned char *data, unsigned char bytes){while(status & (1<<BUSY)); /* Bus is busy wait (or exit with error code) */while(TWCR & (1<<TWSTO));/* copy the needed data and state info to our local I2C command structure */twi_address = address;twi_data = data;twi_bytes = bytes;twi_ddr = TW_WRITE;retry_cnt = 0;/* Generate start condition, the remainder of the transfer is interrupt driven andwill be performed in the background */TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);status |= (1<<BUSY);}/***********************************************************Function Name: I2CInt_readDataFunction Description: This funcion is responsible forreading the specified number of bytes from a slavedevice.Inputs: address: the slave address to read fromdata: a pointer to where the data will be storedbytes: the number of bytes to readOutputs: none***********************************************************/void I2CInt_readData(unsigned char address, unsigned char *data, unsigned char bytes){/* Bus is busy wait (or exit with error code) */while(status & (1<<BUSY));twi_address = address;twi_data = data;twi_bytes = bytes;twi_ddr = TW_READ;retry_cnt = 0;/* Generate start condition, the remainder of the transfer is interrupt driven andwill be performed in the background */TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);status |= (1<<BUSY);}/***********************************************************Function Name: I2CInt_isI2cBusyFunction Description: This funcion is responsible forindicating if the I2C bus is currently busy to externalmodules.device.Inputs: noneOutputs: bool_t - indicating if bus is busy***********************************************************/bool_t I2CInt_isI2cBusy(void){bool_t retVal = FALSE;if ( (status & (1<<BUSY)) != 0){retVal = TRUE;}return(retVal);}/***********************************************************Function Name: <interrupt handler for I2C>Function Description: This function is responsible forimplementing the control logic needed to perform aread or write operation with an I2C slave.Inputs: noneOutputs: none***********************************************************/SIGNAL(SIG_2WIRE_SERIAL){unsigned char TWI_status = TWSR & TW_STATUS_MASK; /* grab just the status bits *//* the entire I2C handler is state-based...determinewhat needs to be done based on TWI_status */switch(TWI_status){case TW_START: /* Start condition */case TW_REP_START: /* Repeated start condition */if(retry_cnt > MAX_TWI_RETRIES){/* generate stop condition if we've reached our retry limit */TWCR |= (1<<TWINT)|(1<<TWSTO);status &= ~(1<<BUSY);return;}/* indicate read or write */TWDR = (twi_address<<1) + twi_ddr;/* TWSTA must be cleared...also clears TWINT */TWCR &= ~(1<<TWSTA);break;case TW_MT_SLA_ACK: /* Slave acknowledged address, */retry_cnt = 0;/* tx the data, and increment the data pointer */TWDR = *twi_data;twi_data++;/* clear the int to continue */TWCR |= (1<<TWINT);break;case TW_MT_SLA_NACK: /* Slave didn't acknowledge address, */case TW_MR_SLA_NACK:retry_cnt++;/* retry...*/TWCR |= (1<<TWINT)|(1<<TWSTA)|(1<<TWSTO);break;case TW_MT_DATA_ACK: /* Slave Acknowledged data, */if(--twi_bytes > 0){/* more data to send, so send it */TWDR = *twi_data;twi_data++;TWCR |= (1<<TWINT);}else{/* generate the stop condition if needed */TWCR |= (1<<TWSTO)|(1<<TWINT);status &= ~(1<<BUSY);}break;case TW_MT_DATA_NACK: /* Slave didn't acknowledge data *//* send the stop condition */TWCR |= (1<<TWINT)|(1<<TWSTO);status &= ~(1<<BUSY);break;case TW_MR_SLA_ACK: /* Slave acknowledged address */if(--twi_bytes > 0){/* if there is more than one byte to read, acknowledge */TWCR |= (1<<TWEA)|(1<<TWINT);}else{/* no acknowledge */TWCR |= (1<<TWINT);}break;case TW_MR_DATA_ACK: /* Master acknowledged data *//* grab the received data */*twi_data = TWDR;twi_data++;if(--twi_bytes > 0){/* get the next data byte and ack */TWCR |= (1<<TWEA)|(1<<TWINT);}else{/* clear out the enable acknowledge bit */TWCR &= ~(1<<TWEA);}break;case TW_MR_DATA_NACK: /* Master didn't acknowledge data -> end of read process *//* read data, and generate the stop condition */*twi_data = TWDR;TWCR |= (1<<TWSTO)|(1<<TWINT);status &= ~(1<<BUSY);break;}}