603 lines
17 KiB
C
603 lines
17 KiB
C
//*****************************************************************************
|
|
//
|
|
// camera.c
|
|
//
|
|
// Driver for the camera controller module
|
|
//
|
|
// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
|
|
//
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
//
|
|
// Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
//
|
|
// Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the
|
|
// distribution.
|
|
//
|
|
// Neither the name of Texas Instruments Incorporated nor the names of
|
|
// its contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \addtogroup camera_api
|
|
//! @{
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#include "inc/hw_types.h"
|
|
#include "inc/hw_ints.h"
|
|
#include "inc/hw_memmap.h"
|
|
#include "inc/hw_camera.h"
|
|
#include "inc/hw_apps_config.h"
|
|
#include "interrupt.h"
|
|
#include "camera.h"
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Resets the Camera core
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//!
|
|
//! This function resets the camera core
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraReset(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Reset the camera
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_SYSCONFIG) = CAMERA_CC_SYSCONFIG_SOFT_RESET;
|
|
|
|
//
|
|
// Wait for reset completion
|
|
//
|
|
while(!(HWREG(ulBase + CAMERA_O_CC_SYSSTATUS)&
|
|
CAMERA_CC_SYSSTATUS_RESET_DONE2))
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Configures camera parameters
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param ulHSPol sets the HSync polarity
|
|
//! \param ulVSPol sets the VSync polarity
|
|
//! \param ulFlags are configuration flags
|
|
//!
|
|
//! This function sets different camera parameters.
|
|
//!
|
|
//! The parameter \e ulHSPol should be on the follwoing:
|
|
//! - \b CAM_HS_POL_HI
|
|
//! - \b CAM_HS_POL_LO
|
|
//!
|
|
//! The parameter \e ulVSPol should be on the follwoing:
|
|
//! - \b CAM_VS_POL_HI
|
|
//! - \b CAM_VS_POL_LO
|
|
//!
|
|
//! The parameter \e ulFlags can be logical OR of one or more of the follwoing
|
|
//! or 0:
|
|
//! - \b CAM_PCLK_RISE_EDGE
|
|
//! - \b CAM_PCLK_FALL_EDGE
|
|
//! - \b CAM_ORDERCAM_SWAP
|
|
//! - \b CAM_NOBT_SYNCHRO
|
|
//! - \b CAM_IF_SYNCHRO
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraParamsConfig(unsigned long ulBase, unsigned long ulHSPol,
|
|
unsigned long ulVSPol, unsigned long ulFlags)
|
|
{
|
|
unsigned long ulReg;
|
|
|
|
//
|
|
// Read the register
|
|
//
|
|
ulReg = HWREG(ulBase + CAMERA_O_CC_CTRL);
|
|
|
|
//
|
|
// Set the requested parameter
|
|
//
|
|
ulFlags = (ulFlags|ulHSPol|ulVSPol);
|
|
ulReg = ((ulReg & ~(CAMERA_CC_CTRL_NOBT_SYNCHRO |
|
|
CAMERA_CC_CTRL_NOBT_HS_POL |
|
|
CAMERA_CC_CTRL_NOBT_VS_POL |
|
|
CAMERA_CC_CTRL_BT_CORRECT |
|
|
CAMERA_CC_CTRL_PAR_ORDERCAM |
|
|
CAMERA_CC_CTRL_PAR_CLK_POL )) | ulFlags);
|
|
|
|
//
|
|
// Write the configuration
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL)=ulReg;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Set the internal clock divider
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param ulCamClkIn is input to camera module
|
|
//! \param ulXClk defines the output required
|
|
//!
|
|
//! This function sets the internal clock divider based on \e ulCamClkIn to
|
|
//! generate XCLK as specified be \e ulXClk. Maximum suppoter division is 30
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraXClkConfig(unsigned long ulBase, unsigned long ulCamClkIn,
|
|
unsigned long ulXClk)
|
|
{
|
|
unsigned long ulReg;
|
|
unsigned long ucDiv;
|
|
|
|
//
|
|
// Read the register
|
|
//
|
|
ulReg = HWREG(ulBase + CAMERA_O_CC_CTRL_XCLK);
|
|
|
|
//
|
|
// Mask XCLK divider value
|
|
//
|
|
ulReg &= ~(CAMERA_CC_CTRL_XCLK_XCLK_DIV_M);
|
|
|
|
//
|
|
// Compute the divider
|
|
//
|
|
ucDiv = ((ulCamClkIn)/ulXClk);
|
|
|
|
//
|
|
// Max supported division is 30
|
|
//
|
|
if(ucDiv > 30)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Set and write back the configuration
|
|
//
|
|
ulReg |= ucDiv;
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL_XCLK) = ulReg;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Sets the internal divide in specified mode
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param bXClkFlags decides the divide mode
|
|
//!
|
|
//! This function sets the internal divide in specified mode.
|
|
//!
|
|
//! The parameter \e bXClkFlags should be one of the following :
|
|
//!
|
|
//! - \b CAM_XCLK_STABLE_LO
|
|
//! - \b CAM_XCLK_STABLE_HI
|
|
//! - \b CAM_XCLK_DIV_BYPASS
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraXClkSet(unsigned long ulBase, unsigned char bXClkFlags)
|
|
{
|
|
unsigned long ulReg;
|
|
|
|
//
|
|
// Read and Mask XTAL Divider config.
|
|
//
|
|
ulReg = (HWREG(ulBase + CAMERA_O_CC_CTRL_XCLK) &
|
|
~(CAMERA_CC_CTRL_XCLK_XCLK_DIV_M));
|
|
|
|
//
|
|
// Set config. base on parameter flag
|
|
//
|
|
switch(bXClkFlags)
|
|
{
|
|
|
|
case CAM_XCLK_STABLE_HI : ulReg |= 0x00000001;
|
|
break;
|
|
|
|
case CAM_XCLK_DIV_BYPASS: ulReg |= 0x0000001F;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Write the config.
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL_XCLK) = ulReg;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Enable camera DMA
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//!
|
|
//! This function enables transfer request to DMA from camera. DMA specific
|
|
//! configuration has to be done seperately.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraDMAEnable(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Enable DMA
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL_DMA) |= CAMERA_CC_CTRL_DMA_DMA_EN;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Disable camera DMA
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//!
|
|
//! This function masks transfer request to DMA from camera.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraDMADisable(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Disable DMA
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL_DMA) &= ~CAMERA_CC_CTRL_DMA_DMA_EN;
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Sets the FIFO threshold for DMA transfer request
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param ulThreshold specifies the FIFO threshold
|
|
//!
|
|
//! This function sets the FIFO threshold for DMA transfer request.
|
|
//! Parameter \e ulThreshold can range from 1 - 64
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraThresholdSet(unsigned long ulBase, unsigned long ulThreshold)
|
|
{
|
|
//
|
|
// Read and Mask DMA threshold field
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL_DMA) &= ~CAMERA_CC_CTRL_DMA_FIFO_THRESHOLD_M;
|
|
//
|
|
// Write the new threshold value
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL_DMA) |= (ulThreshold -1);
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Register camera interrupt handler
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param pfnHandler hold pointer to interrupt handler
|
|
//!
|
|
//! This function registers and enables global camera interrupt from the
|
|
//! interrupt controller. Individual camera interrupts source
|
|
//! should be enabled using \sa CameraIntEnable().
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
|
|
{
|
|
//
|
|
// Register the interrupt handler.
|
|
//
|
|
IntRegister(INT_CAMERA, pfnHandler);
|
|
|
|
//
|
|
// Enable the Camera interrupt.
|
|
//
|
|
IntEnable(INT_CAMERA);
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Un-Register camera interrupt handler
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//!
|
|
//! This function unregisters and disables global camera interrupt from the
|
|
//! interrupt controller.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraIntUnregister(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Disable the interrupt.
|
|
//
|
|
IntDisable(INT_CAMERA);
|
|
|
|
//
|
|
// Unregister the interrupt handler.
|
|
//
|
|
IntUnregister(INT_CAMERA);
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//! Enables individual camera interrupt sources.
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param ulIntFlags is the bit mask of the interrupt sources to be enabled.
|
|
//!
|
|
//! This function enables individual camera interrupt sources.
|
|
//!
|
|
//! the parameter \e ulIntFlags should be logical OR of one or more of the
|
|
//! following:
|
|
//!
|
|
//! - \b CAM_INT_DMA
|
|
//! - \b CAM_INT_FE
|
|
//! - \b CAM_INT_FSC_ERR
|
|
//! - \b CAM_INT_FIFO_NOEMPTY
|
|
//! - \b CAM_INT_FIFO_FULL
|
|
//! - \b CAM_INT_FIFO_THR
|
|
//! - \b CAM_INT_FIFO_OF
|
|
//! - \b CAN_INT_FIFO_UR
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
|
|
{
|
|
//
|
|
// unmask Camera DMA done interrupt
|
|
//
|
|
if(ulIntFlags & CAM_INT_DMA)
|
|
{
|
|
HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ((1<<8));
|
|
}
|
|
|
|
//
|
|
// Enable specific camera interrupts
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_IRQENABLE) |= ulIntFlags;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//! Disables individual camera interrupt sources.
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param ulIntFlags is the bit mask of the interrupt sources to be disabled.
|
|
//!
|
|
//! This function disables individual camera interrupt sources.
|
|
//!
|
|
//! The parameter \e ulIntFlags should be logical OR of one or more of the
|
|
//! values as defined in CameraIntEnable().
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
|
|
{
|
|
//
|
|
// Mask Camera DMA done interrupt
|
|
//
|
|
if(ulIntFlags & CAM_INT_DMA)
|
|
{
|
|
HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ((1<<8));
|
|
}
|
|
|
|
//
|
|
// Disable specific camera interrupts
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_IRQENABLE) &= ~ulIntFlags;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Returns the current interrupt status,
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param ulBase is the base address of the camera module.
|
|
//!
|
|
//! This functions returns the current interrupt status for the camera.
|
|
//!
|
|
//! \return Returns the current interrupt status, enumerated as a bit field of
|
|
//! values described in CameraIntEnable().
|
|
//******************************************************************************
|
|
unsigned long CameraIntStatus(unsigned long ulBase)
|
|
{
|
|
unsigned ulIntFlag;
|
|
|
|
//
|
|
// Read camera interrupt
|
|
//
|
|
ulIntFlag = HWREG(ulBase + CAMERA_O_CC_IRQSTATUS);
|
|
|
|
//
|
|
//
|
|
// Read camera DMA doner interrupt
|
|
//
|
|
if(HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED) & (1<<8))
|
|
{
|
|
ulIntFlag |= CAM_INT_DMA;
|
|
}
|
|
|
|
//
|
|
// Return status
|
|
//
|
|
return(ulIntFlag);
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//! Clears individual camera interrupt sources.
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param ulIntFlags is the bit mask of the interrupt sources to be Clears.
|
|
//!
|
|
//! This function Clears individual camera interrupt sources.
|
|
//!
|
|
//! The parameter \e ulIntFlags should be logical OR of one or more of the
|
|
//! values as defined in CameraIntEnable().
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraIntClear(unsigned long ulBase, unsigned long ulIntFlags)
|
|
{
|
|
//
|
|
// Clear DMA done int status
|
|
//
|
|
if(ulIntFlags & CAM_INT_DMA)
|
|
{
|
|
HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ((1<<8));
|
|
}
|
|
|
|
//
|
|
// Clear the interrupts
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_IRQSTATUS) = ulIntFlags;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Starts image capture
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//!
|
|
//! This function starts the image capture over the configured camera interface
|
|
//! This function should be called after configuring the camera module
|
|
//! completele
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraCaptureStart(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Set the mode
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL) &= ~0xF;
|
|
|
|
//
|
|
// Enable image capture
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL) |= CAMERA_CC_CTRL_CC_EN;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Stops image capture
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param bImmediate is \b true to stop capture imeediately else \b flase.
|
|
//!
|
|
//! This function stops the image capture over the camera interface.
|
|
//! The capture is stopped either immediatelt or at the end of current frame
|
|
//! based on \e bImmediate parameter.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraCaptureStop(unsigned long ulBase, tBoolean bImmediate)
|
|
{
|
|
if(bImmediate)
|
|
{
|
|
//
|
|
// Stop capture immediately
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL) &= ~CAMERA_CC_CTRL_CC_FRAME_TRIG;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Stop capture at the end of frame
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL) |= CAMERA_CC_CTRL_CC_FRAME_TRIG;
|
|
}
|
|
|
|
//
|
|
// Request camera to stop capture
|
|
//
|
|
HWREG(ulBase + CAMERA_O_CC_CTRL) &= ~CAMERA_CC_CTRL_CC_EN;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
//! Reads the camera buffer (FIFO)
|
|
//!
|
|
//! \param ulBase is the base address of the camera module.
|
|
//! \param pBuffer is the pointer to the read buffer
|
|
//! \param ucSize specifies the size to data to be read
|
|
//!
|
|
//! This function reads the camera buffer (FIFO).
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//******************************************************************************
|
|
void CameraBufferRead(unsigned long ulBase, unsigned long *pBuffer,
|
|
unsigned char ucSize)
|
|
{
|
|
unsigned char *pCamBuff;
|
|
unsigned char i;
|
|
|
|
//
|
|
// Initilize a pointer to ecamera buffer
|
|
//
|
|
pCamBuff = (unsigned char *)CAM_BUFFER_ADDR;
|
|
|
|
//
|
|
// Read out requested data
|
|
//
|
|
for(i=0; i < ucSize; i++)
|
|
{
|
|
*(pBuffer+i) = *(pCamBuff + i);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Close the Doxygen group.
|
|
//! @}
|
|
//
|
|
//*****************************************************************************
|