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>
49
#include <avr/twi.h>
50
#include <avr/signal.h>
51
#include <avr/interrupt.h>
52
#include "CamConfig.h"
53
#include "CommonDefs.h"
54
 
55
/*  Local Variables */
56
 
57
/* These variables are used as storage space for the current
58
   I2C command being sent over the interface.  They need to
59
   be volatile since they are dealt with an the TWI ISR */
60
volatile static unsigned char twi_address;
61
volatile static unsigned char *twi_data;
62
volatile static unsigned char twi_ddr;
63
volatile static unsigned char twi_bytes;
64
volatile static unsigned char status;
65
volatile static unsigned char retry_cnt;
66
 
67
/* 	Local Structures and Typedefs */
68
 
69
/*  Extern Variables */
70
 
71
/*  Definitions */
72
/* Bit definitions for the tw_status register */
73
#define MAX_TWI_RETRIES 2
74
#define BUSY 7
75
 
76
/***********************************************************
77
	Function Name: I2CInt_init
78
	Function Description: This function is responsible
79
	for setting up the registers needed for the TWI 
80
	interface
81
 
82
	Inputs:  none
83
	Outputs: none
84
***********************************************************/	
85
void I2CInt_init(void)
86
{
87
	TWSR = 0;
88
 
89
	/* init the speed of the I2C interface, running at
90
    100 Kbps */
91
	TWBR = (FOSC / I2C_SPEED - 16)/2;
92
}
93
 
94
/***********************************************************
95
	Function Name: I2CInt_writeData
96
	Function Description: This function is responsible for
97
	initiating the process of writing a sequence of bytes
98
	an I2C slave address.  This function will try to write
99
	the data three times before giving up.
100
	Inputs: address: the address of the I2C slave device
101
			data: a pointer to the data to be written 
102
				  to the slave...for camera interfacing,
103
				  the data follows a <register #><data>
104
				  format
105
			bytes: the number of bytes to write 
106
	Outputs: none
107
***********************************************************/
108
void I2CInt_writeData(unsigned char address, unsigned char *data, unsigned char bytes)
109
{
110
	while(status & (1<<BUSY));		/* Bus is busy wait (or exit with error code) */
111
	while(TWCR & (1<<TWSTO));
112
 
113
	/* copy the needed data and state info to our local I2C command structure */
114
	twi_address = address;
115
	twi_data = data;
116
	twi_bytes = bytes;
117
	twi_ddr = TW_WRITE;
118
 
119
	retry_cnt = 0;
120
 
121
	/* Generate start condition, the remainder of the transfer is interrupt driven and
122
	   will be performed in the background */
123
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);
124
 
125
	status |= (1<<BUSY);
126
}
127
 
128
/***********************************************************
129
	Function Name: I2CInt_readData
130
	Function Description: This funcion is responsible for
131
	reading the specified number of bytes from a slave
132
	device.
133
	Inputs:  address: the slave address to read from
134
			 data: a pointer to where the data will be stored
135
			 bytes: the number of bytes to read
136
	Outputs: none
137
***********************************************************/
138
void I2CInt_readData(unsigned char address, unsigned char *data, unsigned char bytes)
139
{
140
    /* Bus is busy wait (or exit with error code) */
141
	while(status & (1<<BUSY));									
142
 
143
	twi_address = address;
144
	twi_data = data;
145
	twi_bytes = bytes;
146
	twi_ddr = TW_READ;
147
 
148
	retry_cnt = 0;
149
 
150
	/* Generate start condition, the remainder of the transfer is interrupt driven and
151
	   will be performed in the background */
152
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);
153
 
154
	status |= (1<<BUSY);
155
}
156
 
157
/***********************************************************
158
	Function Name: I2CInt_isI2cBusy
159
	Function Description: This funcion is responsible for
160
	indicating if the I2C bus is currently busy to external
161
	modules.
162
	device.
163
	Inputs:  none
164
	Outputs: bool_t - indicating if bus is busy
165
***********************************************************/
166
bool_t I2CInt_isI2cBusy(void)
167
{
168
	bool_t retVal = FALSE;
169
	if ( (status & (1<<BUSY)) != 0)
170
	{
171
		retVal = TRUE;
172
	}
173
 
174
	return(retVal);
175
}
176
 
177
/***********************************************************
178
	Function Name: <interrupt handler for I2C>
179
	Function Description: This function is responsible for
180
	implementing the control logic needed to perform a
181
	read or write operation with an I2C slave.
182
	Inputs:  none
183
	Outputs: none
184
***********************************************************/
185
SIGNAL(SIG_2WIRE_SERIAL)
186
{
187
	unsigned char TWI_status = TWSR & TW_STATUS_MASK;   /* grab just the status bits */
188
 
189
    /* the entire I2C handler is state-based...determine
190
    what needs to be done based on TWI_status */
191
	switch(TWI_status) 
192
    {
193
        case TW_START:									/* Start condition */
194
        case TW_REP_START:								/* Repeated start condition */
195
            if(retry_cnt > MAX_TWI_RETRIES) 
196
            {
197
                /* generate stop condition if we've reached our retry limit */
198
                TWCR |= (1<<TWINT)|(1<<TWSTO);					
199
                status &= ~(1<<BUSY);								
200
                return;												
201
            }
202
            /* indicate read or write */
203
            TWDR = (twi_address<<1) + twi_ddr;	
204
            /* TWSTA must be cleared...also clears TWINT */
205
            TWCR &= ~(1<<TWSTA);
206
            break;
207
 
208
        case TW_MT_SLA_ACK:							/* Slave acknowledged address, */
209
            retry_cnt = 0;					
210
            /* tx the data, and increment the data pointer */
211
            TWDR = *twi_data;										
212
            twi_data++;			
213
 
214
            /* clear the int to continue */
215
            TWCR |= (1<<TWINT);						
216
            break;
217
 
218
        case TW_MT_SLA_NACK:							/* Slave didn't acknowledge address, */
219
        case TW_MR_SLA_NACK:
220
            retry_cnt++;		
221
 
222
            /* retry...*/
223
            TWCR |= (1<<TWINT)|(1<<TWSTA)|(1<<TWSTO);	
224
            break;
225
 
226
        case TW_MT_DATA_ACK:							/* Slave Acknowledged data, */
227
            if(--twi_bytes > 0) 
228
            {						
229
                /* more data to send, so send it */
230
                TWDR = *twi_data;									
231
                twi_data++;											
232
                TWCR |= (1<<TWINT);								
233
            }
234
            else 
235
            {
236
                /* generate the stop condition if needed */
237
                TWCR |= (1<<TWSTO)|(1<<TWINT);					
238
                status &= ~(1<<BUSY);								
239
            }
240
            break;
241
 
242
        case TW_MT_DATA_NACK:							/* Slave didn't acknowledge data */
243
            /* send the stop condition */
244
            TWCR |= (1<<TWINT)|(1<<TWSTO);						
245
            status &= ~(1<<BUSY);									
246
            break;
247
 
248
        case TW_MR_SLA_ACK:                             /* Slave acknowledged address */
249
            if(--twi_bytes > 0) 
250
            {
251
                /* if there is more than one byte to read, acknowledge */
252
                TWCR |= (1<<TWEA)|(1<<TWINT);	
253
            }
254
			else
255
            {
256
                /* no acknowledge */
257
                TWCR |= (1<<TWINT);					
258
            }
259
            break;
260
 
261
        case TW_MR_DATA_ACK: 							/* Master acknowledged data */
262
 
263
            /* grab the received data */
264
            *twi_data = TWDR;										
265
            twi_data++;											
266
            if(--twi_bytes > 0) 
267
            {
268
                /* get the next data byte and ack */
269
                TWCR |= (1<<TWEA)|(1<<TWINT);	
270
            }
271
            else
272
            {
273
                /* clear out the enable acknowledge bit */
274
                TWCR &= ~(1<<TWEA);							
275
            }
276
            break;
277
 
278
        case TW_MR_DATA_NACK:						/* Master didn't acknowledge data -> end of read process */
279
            /* read data, and generate the stop condition */
280
            *twi_data = TWDR;										
281
            TWCR |= (1<<TWSTO)|(1<<TWINT); 						
282
            status &= ~(1<<BUSY);											
283
            break;
284
	}
285
}
286
 
287
 
288
 
289
 
290
 
291
 
292
 
293
 
294