| 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 |   |