Subversion Repositories svnkaklik

Rev

Rev 151 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log

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