Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
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