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: CamInterface.c
|
|
|
28 |
Module Date: 04/12/2004
|
|
|
29 |
Module Auth: John Orlando
|
|
|
30 |
|
|
|
31 |
Description: This file is responsible for providing an
|
|
|
32 |
interface to the OV6620 camera hardware. This includes
|
|
|
33 |
an interface to CamInterface.S for certain low-level,
|
|
|
34 |
optimized camera access routines.
|
|
|
35 |
|
|
|
36 |
Revision History:
|
|
|
37 |
Date Rel Ver. Notes
|
|
|
38 |
4/10/2004 0.1 Module created
|
|
|
39 |
6/30/2004 1.0 Initial release for Circuit Cellar
|
|
|
40 |
contest.
|
|
|
41 |
11/15/2004 1.2 ifdef'd out the resetCam routine, since
|
|
|
42 |
resetting the cam now causes the OV6620's
|
|
|
43 |
clock to not be output (we have to start
|
|
|
44 |
it up after each reset with the external
|
|
|
45 |
tiny12 processor).
|
|
|
46 |
1/16/2005 1.4 Ensure that the TCCR1B register is set so
|
|
|
47 |
nothing is clocking timer1 at startup.
|
|
|
48 |
***********************************************************/
|
|
|
49 |
|
|
|
50 |
/* Includes */
|
|
|
51 |
#include <avr/interrupt.h>
|
|
|
52 |
#include <avr/signal.h>
|
|
|
53 |
#include <avr/sleep.h>
|
|
|
54 |
#include <avr/eeprom.h>
|
|
|
55 |
#include <stdlib.h>
|
|
|
56 |
#include <string.h>
|
|
|
57 |
#include "CommonDefs.h"
|
|
|
58 |
#include "CamInterface.h"
|
|
|
59 |
#include "Utility.h"
|
|
|
60 |
#include "UIMgr.h"
|
|
|
61 |
#include "Executive.h"
|
|
|
62 |
#include "UartInterface.h"
|
|
|
63 |
|
|
|
64 |
/* Local Variables */
|
|
|
65 |
|
|
|
66 |
/* Local Structures and Typedefs */
|
|
|
67 |
|
|
|
68 |
/* Definitions */
|
|
|
69 |
//#define OUTPUT_INITIAL_COLOR_MAP 1
|
|
|
70 |
|
|
|
71 |
#define FAST_ACQUIRE 1
|
|
|
72 |
#define CAM_G_BUS PINB
|
|
|
73 |
#define CAM_G_BUS_DIR DDRB
|
|
|
74 |
#define CAM_RB_BUS PINC
|
|
|
75 |
#define CAM_RB_BUS_DIR DDRC
|
|
|
76 |
|
|
|
77 |
#define CAM_CONTROL_PORT PORTD
|
|
|
78 |
#define CAM_CONTROL_PORT_DIR DDRD
|
|
|
79 |
#define CAM_RESET_LINE BIT7
|
|
|
80 |
#define CAM_PIXEL_CLK_COUNT BIT5
|
|
|
81 |
#define CAM_HREF BIT4
|
|
|
82 |
#define CAM_PIXEL_CLK_INT BIT3
|
|
|
83 |
#define CAM_VSYNC BIT2
|
|
|
84 |
|
|
|
85 |
/* Global Variables */
|
|
|
86 |
/* NOTE: This file MUST appear first in the Makefile for these variables to
|
|
|
87 |
be placed properly in RAM */
|
|
|
88 |
|
|
|
89 |
/* The colorMap[] table provides the membership lookup table to convert
|
|
|
90 |
RGB or YUV pixel values into actual colors. The membership table contains
|
|
|
91 |
16 elements for each color channel, concatenated together. The Red (or Y)
|
|
|
92 |
value is located in the first 16 bytes, the G (or U) value is located in
|
|
|
93 |
the second 16 bytes, and the B (or V) value is located in the last 16 bytes:
|
|
|
94 |
|
|
|
95 |
----------------------------------------------------------------------------------
|
|
|
96 |
|red0|red1|red2|...|red15|green0|green1|green2|...|green15|blue0|blue1|...|blue15|
|
|
|
97 |
mem:|0x00 0x01 0x02 0x15 0x16 0x17 0x18 0x31 0x32 0x33 0x47 |
|
|
|
98 |
---------------------------------------------------------------------------------
|
|
|
99 |
Thus, the red lookup is accessed at colorMap+0, the green lookup is accessed
|
|
|
100 |
at colorMap+16, and the blue lookup is accessed at colorMap+32. */
|
|
|
101 |
unsigned char colorMap[NUM_ELEMENTS_IN_COLOR_MAP] __attribute__ ((section (".noinit")));
|
|
|
102 |
|
|
|
103 |
/* Extern Variables */
|
|
|
104 |
/* These two buffers hold the current and previous lines
|
|
|
105 |
of pixel data. They are sized to the worst case scenario,
|
|
|
106 |
where the color changes between every pixel (unrealistic).
|
|
|
107 |
The format of each buffer is for all the even bytes to hold
|
|
|
108 |
the run-length, and the odd bytes to hold the color data. */
|
|
|
109 |
|
|
|
110 |
/* In addition, if we are in frameDump mode, we use these buffers
|
|
|
111 |
to store the acquired line data...we are actually grabbing ALL of the
|
|
|
112 |
pixels in a line (176) instead of the 88 we get normally during tracking.
|
|
|
113 |
But since we have enough to hold 88-RLE blocks, we already have the 176
|
|
|
114 |
allocated for this... */
|
|
|
115 |
unsigned char currentLineBuffer[LENGTH_OF_LINE_BUFFER];
|
|
|
116 |
unsigned char previousLineBuffer[LENGTH_OF_LINE_BUFFER];
|
|
|
117 |
|
|
|
118 |
/* Extern Functions */
|
|
|
119 |
/* These functions are located in assembly files, and thus
|
|
|
120 |
must be externed here so they can be referenced in the source below. */
|
|
|
121 |
extern void CamIntAsm_waitForNewTrackingFrame(unsigned char *pBuffer, unsigned char *pMemLookup);
|
|
|
122 |
extern void CamIntAsm_waitForNewDumpFrame(unsigned char *pCurrBuffer, unsigned char *pPrevBuffer);
|
|
|
123 |
extern void CamIntAsm_acquireTrackingLine(unsigned char *pBuffer, unsigned char *pMemLookup);
|
|
|
124 |
extern void CamIntAsm_acquireDumpLine(unsigned char *pCurrBuffer, unsigned char *pPrevBuffer);
|
|
|
125 |
|
|
|
126 |
/***********************************************************
|
|
|
127 |
Function Name: CamInt_init
|
|
|
128 |
Function Description: This function is responsible
|
|
|
129 |
for initializing the camera interface. This includes
|
|
|
130 |
setting up the i/o ports that are used to read the
|
|
|
131 |
camera busses, as well as resetting the camera.
|
|
|
132 |
Inputs: none
|
|
|
133 |
Outputs: none
|
|
|
134 |
***********************************************************/
|
|
|
135 |
void CamInt_init(void)
|
|
|
136 |
{
|
|
|
137 |
#if OUTPUT_INITIAL_COLOR_MAP
|
|
|
138 |
unsigned char asciiBuffer[5];
|
|
|
139 |
unsigned char i;
|
|
|
140 |
#endif
|
|
|
141 |
|
|
|
142 |
/* set up the mega8 ports that will be interfacing
|
|
|
143 |
with the camera */
|
|
|
144 |
CAM_CONTROL_PORT_DIR |= (1<<CAM_RESET_LINE); /* cam reset is output */
|
|
|
145 |
CAM_CONTROL_PORT_DIR |= 0x80; /* set just the MSB as an output */
|
|
|
146 |
CAM_CONTROL_PORT_DIR &= 0xFB; /* make sure bit2 is clear (input) */
|
|
|
147 |
CAM_CONTROL_PORT &= 0x7F; /* set reset line low */
|
|
|
148 |
CAM_G_BUS_DIR &= 0xF0; /* 4-bit G bus all inputs */
|
|
|
149 |
CAM_G_BUS_DIR |= 0xF0; /* disable the pull-up on PB4 and PB5 */
|
|
|
150 |
CAM_RB_BUS_DIR &= 0xF0; /* 4-bit RB bus all inputs */
|
|
|
151 |
|
|
|
152 |
/* ensure that timer1 is disabled to start...eventually, when PCLK needs
|
|
|
153 |
to feed timer1 through the external counter, it will be enabled on an
|
|
|
154 |
"as needed" basis...*/
|
|
|
155 |
TCCR1B &= ~( (1<<CS12)|(1<<CS11)|(1<<CS10) );
|
|
|
156 |
|
|
|
157 |
/* we'll turn on the interrupt after we assign the initial TCNT value */
|
|
|
158 |
|
|
|
159 |
/* set up External Interrupt1 to interrupt us on rising edges (HREF)...
|
|
|
160 |
this is needed to indicate when the first pixel of each line is about to start, so
|
|
|
161 |
we can synch up with it...this interrupt will be disabled once HREF goes high */
|
|
|
162 |
|
|
|
163 |
MCUCR |= (1<<ISC11) | (1<<ISC10); /* rising edge interrupt */
|
|
|
164 |
/* the interrupt will be enabled when we are ready to detect the rising edge of
|
|
|
165 |
HREF...its now primed and ready to go */
|
|
|
166 |
|
|
|
167 |
/* set up External Interrupt0 to interrupt us on rising edges (VSYNC) */
|
|
|
168 |
MCUCR |= (1<<ISC01) | (1<<ISC00); /* rising edge interrupt */
|
|
|
169 |
GICR |= (1<<INT0); /* interrupt request enabled */
|
|
|
170 |
|
|
|
171 |
/* set up TimerO to count and be clocked from an external pulse source
|
|
|
172 |
(HREF) on falling edges...eventually, we need to enable the interrupt
|
|
|
173 |
for this! FIX THIS */
|
|
|
174 |
TCCR0 = (1<<CS02)|(1<<CS01)|(0<<CS00);
|
|
|
175 |
|
|
|
176 |
/* setting up the PCLK counter with Timer1 will be done right after
|
|
|
177 |
we start receiving pixels in each line...we sacrifice the first pixel
|
|
|
178 |
in each line, but we'll account for it...*/
|
|
|
179 |
|
|
|
180 |
/* set up the mega8 so that its sleep mode puts it in an IDLE sleep
|
|
|
181 |
mode, where it can wake up as fast as possible */
|
|
|
182 |
set_sleep_mode(SLEEP_MODE_IDLE);
|
|
|
183 |
/* umm....we need to actually enable the sleep mode...*/
|
|
|
184 |
MCUCR |= 0x80;
|
|
|
185 |
|
|
|
186 |
/* initialize the memLookup table */
|
|
|
187 |
memset(colorMap,0x00,NUM_ELEMENTS_IN_COLOR_MAP);
|
|
|
188 |
|
|
|
189 |
/* read the color map out of EEPROM */
|
|
|
190 |
eeprom_read_block(colorMap, (unsigned char*)0x01,NUM_ELEMENTS_IN_COLOR_MAP);
|
|
|
191 |
|
|
|
192 |
#if OUTPUT_INITIAL_COLOR_MAP
|
|
|
193 |
UIMgr_txBuffer("\r\n",2);
|
|
|
194 |
for (i=0; i<NUM_ELEMENTS_IN_COLOR_MAP; i++)
|
|
|
195 |
{
|
|
|
196 |
memset(asciiBuffer,0x00,5);
|
|
|
197 |
itoa(colorMap[i],asciiBuffer,10);
|
|
|
198 |
UIMgr_txBuffer(asciiBuffer,3);
|
|
|
199 |
UIMgr_txBuffer(" ",1);
|
|
|
200 |
if (i==15 || i == 31)
|
|
|
201 |
{
|
|
|
202 |
/* break up the output */
|
|
|
203 |
UIMgr_txBuffer("\r\n",2);
|
|
|
204 |
}
|
|
|
205 |
}
|
|
|
206 |
#endif
|
|
|
207 |
|
|
|
208 |
#ifndef NO_CRYSTAL
|
|
|
209 |
CamInt_resetCam();
|
|
|
210 |
#endif
|
|
|
211 |
}
|
|
|
212 |
|
|
|
213 |
/***********************************************************
|
|
|
214 |
Function Name: CamInt_resetCam
|
|
|
215 |
Function Description: This function is responsible
|
|
|
216 |
for resetting the camera. This is accomplished by
|
|
|
217 |
toggling the reset line on the OV6620 for ~100 mS.
|
|
|
218 |
Inputs: none
|
|
|
219 |
Outputs: none
|
|
|
220 |
IMPORTANT NOTE: This function has effectively been removed
|
|
|
221 |
since resetting the camera now causes the camera to not
|
|
|
222 |
output the clock signal. Thus, if we reset the cam, the
|
|
|
223 |
AVR has no clock, and thus doesn't run...
|
|
|
224 |
***********************************************************/
|
|
|
225 |
void CamInt_resetCam(void)
|
|
|
226 |
{
|
|
|
227 |
|
|
|
228 |
#if 0
|
|
|
229 |
CAM_CONTROL_PORT |= (1<<CAM_RESET_LINE); /* cam reset line high */
|
|
|
230 |
Utility_delay(500);
|
|
|
231 |
CAM_CONTROL_PORT &= (0<<CAM_RESET_LINE); /* cam reset line low */
|
|
|
232 |
Utility_delay(100);
|
|
|
233 |
#endif
|
|
|
234 |
}
|
|
|
235 |
|
|
|
236 |
|