SAMA5D3 + Linux + Live View with ISI Interface

Discussion around products based on ARM Cortex-A5 core.

Moderator: nferre

anku
Posts: 3
Joined: Thu Nov 24, 2016 11:08 am

SAMA5D3 + Linux + Live View with ISI Interface

Thu Nov 24, 2016 11:22 am

Hi

We have a hardware with a SAMA5D3x CPU and a ADV7280 Video Codec connected to the ISI interface. Does anyone know how to display a live view in Linux. The connection from ADV7280 to the SAMA5D3x is working. And now we don't really know how to show the live view in Linux. We found an example that uses the hardware of the SAMA5D3x to display a live view. But this example is a bare metal software and not for Linux. What can we do to use the ISI preview mechanism that transfers the live image to a overlay buffer of the LCD controller? The bare metal example is part of this here:
http://www.atmel.com/tools/SAMA5D3SOFTWAREPACKAGE.aspx


-------------------------------------------------------------------------------------
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2013, Atmel Corporation
*
* All rights reserved.
*
* 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 disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
* ----------------------------------------------------------------------------
*/

/**
* \page isi ISI Example
*
* \section Purpose
*
* This example demonstrates the ISI (Image Sensor Interface) of an SAMA5D3x.
*
* \section Requirements
*
* This package can be used with SAMA5d3x evaluation kits with
* On-board ISI infterface and a external CMOS-type image sensor board.
*
* \section Description
* The provided program uses the Image Sensor Interface to connects a CMOS-type
* image sensor to the processor and displays in VGA format.
*
* \section Usage
* -# Build the program and download it inside the evaluation board. Please
* refer to the
* <a href="http://www.atmel.com/dyn/resources/prod ... /6421B.pdf">
* SAM-BA User Guide</a>, the
* <a href="http://www.atmel.com/dyn/resources/prod ... oc6310.pdf">
* GNU-Based Software Development</a> application note or to the
* <a href="ftp://ftp.iar.se/WWWfiles/arm/Guides/EW ... de.ENU.pdf">
* IAR EWARM User Guide</a>, depending on your chosen solution.
* -# On the computer, open and configure a terminal application
* (e.g. HyperTerminal on Microsoft Windows) with these settings:
* - 115200 bauds
* - 8 bits of data
* - No parity
* - 1 stop bit
* - No flow control
* -# Start the application.
* -# In the terminal window, the following text should appear:
* \code
* -- ISI Example xxx --
* -- SAMxxxxx-xx
* -- Compiled: xxx xx xxxx xx:xx:xx --
* \endcode
* The user can then choose any of the available options to perform the described action.
*
* \section References
* - lcdc.c
* - twi.c
* - twid.c
* - isi.c
*/

/**
* \file
*
* This file contains all the specific code for the isi example.
*/

/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/

#include "board.h"
#include "string.h"

/*----------------------------------------------------------------------------
* Local definitions
*----------------------------------------------------------------------------*/

//#define OV5640_AFC

#define LCD_BASE (DDR_CS_ADDR + 16 * 1024 * 1024)

/** LCD Overlay 1 (OVR1) buffer */
#define ADDR_LCD_BUFFER LCD_BASE

/** TWI clock frequency in Hz. */
#define TWCK 400000

/** Eeprom Pins definition */
#define BOARD_PINS_TWI_ISI PINS_TWI1

/** TWI0 peripheral ID for eeprom device*/
#define BOARD_ID_TWI_ISI ID_TWI1

/** TWI0 base address for eeprom device */
#define BOARD_BASE_TWI_ISI TWI1

#define ISI_BASE ADDR_LCD_BUFFER
#define CODEC_BASE (ADDR_LCD_BUFFER + 0x1000000)

/** Frame Buffer Descriptors */
#define ISI_MAX_PREV_BUFFER 1

/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/

/** Pio pins to configure. */
const Pin pinsTWI[] = {BOARD_PINS_TWI_ISI};
const Pin pin_ISI_RSTN = PIN_ISI_RSTN;
const Pin pPinLCD[] = {PINS_LCD};
const Pin pPinsISI[]= {PINS_ISI};
const Pin pinPCK = PIN_PCK1;

static uint8_t *pOvr1Buffer = (uint8_t*)ADDR_LCD_BUFFER;
static uint8_t *pHeoBuffer = (uint8_t*)CODEC_BASE;
static uint8_t sensorType, formatIdx;

/** TWI driver instance.*/
static Twid twid;

/** Video driver instance */
isi_Video sVideo;

ISI_FrameBufferDescriptors preBufDescList[ISI_MAX_PREV_BUFFER + 1];
ISI_FrameBufferDescriptors codecBufDescList[ISI_MAX_PREV_BUFFER + 1];
#if defined (OV5640_AFC)
static uint8_t afDone = 0;
#endif

static struct capture_size ov_test[5][2] = {
{{ 640, 480 }, { 640, 480 }},
{{ 640, 480 }, { 1600, 1200 }},
{{ 640, 480 }, { 1280, 720 }},
{{ 640, 480 }, { 640, 480 }},
{{ 1280, 720 }, { 640, 360 }},
};

/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief TWI interrupt handler. Forwards the interrupt to the TWI driver handler.
*/
static void TWI1_IrqHandler( void )
{
TWID_Handler( &twid ) ;
}

/**
* \brief TWI interrupt handler. Forwards the interrupt to the TWI driver handler.
*/
static void _lcdInit(void)
{
/* Configure pins. */
PIO_Configure(pPinLCD, PIO_LISTSIZE(pPinLCD));
LCDD_Off();
/* Enable peripheral clock */
PMC_EnablePeripheral(ID_LCDC);
PMC->PMC_SCER = (0x1u << 3);
/* Disable interrupt */
LCDC->LCDC_LCDIDR = 0xFFFFFFFF;
LCDD_On();
LCDD_SetBacklight(0xF0);

/* Configure channels for preview */
LCDC->LCDC_OVR1CFG0 = LCDC_OVR1CFG0_DLBO |
LCDC_OVR1CFG0_BLEN_AHB_BLEN_INCR16 |
LCDC_OVR1CFG0_ROTDIS ;
LCDC->LCDC_OVR1CFG1 = LCDC_BASECFG1_RGBMODE_16BPP_RGB_565;
LCDC->LCDC_OVR1CFG9 = LCDC_OVR1CFG9_GA(0xFF) | LCDC_OVR1CFG9_GAEN;
LCDD_CreateCanvas(LCDD_OVR1, pOvr1Buffer, 16, 0, 0, 640, 480);


/* Configure channels for CODEC */
LCDC->LCDC_HEOCFG0 = LCDC_HEOCFG0_DLBO |
LCDC_HEOCFG0_BLEN_AHB_BLEN_INCR16 |
LCDC_HEOCFG0_BLENUV_AHB_INCR4 |
LCDC_HEOCFG0_ROTDIS ;
LCDC->LCDC_HEOCFG1 = LCDC_HEOCFG1_YUVEN |\
LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE3;
LCDC->LCDC_HEOCFG12 = LCDC_HEOCFG12_GA(0xFF) | LCDC_HEOCFG12_GAEN;
LCDC->LCDC_HEOCFG14 = LCDC_HEOCFG14_CSCRY(0x94)| LCDC_HEOCFG14_CSCRU(0xCC) | LCDC_HEOCFG14_CSCRV(0) | LCDC_HEOCFG14_CSCYOFF;
LCDC->LCDC_HEOCFG15 = LCDC_HEOCFG15_CSCGY(0x94)| LCDC_HEOCFG15_CSCGU(0x387) | LCDC_HEOCFG15_CSCGV(0x3CD) | LCDC_HEOCFG15_CSCUOFF;
LCDC->LCDC_HEOCFG16 = LCDC_HEOCFG16_CSCBY(0x94)| LCDC_HEOCFG16_CSCBU(0) | LCDC_HEOCFG16_CSCBV(0x102) | LCDC_HEOCFG16_CSCVOFF;
LCDD_CreateCanvas(LCDD_HEO, pHeoBuffer, 16, 0, 0, 640, 480);
printf("- LCD ON\n\r");
}


/**
* \brief Frame Buffer Descriptors (FBD)
*/
static void _isiAllocateFBD(void)
{
uint32_t i;
for(i = 0; i <= ISI_MAX_PREV_BUFFER; i++) {
preBufDescList.Current = (uint32_t)ISI_BASE ;
preBufDescList.Control = ISI_DMA_P_CTRL_P_FETCH ;
preBufDescList.Next = (uint32_t)&preBufDescList[i + 1];
}
/* Wrapping to first FBD */
preBufDescList[i-1].Next = (uint32_t)&preBufDescList[0];

for(i = 0; i <= ISI_MAX_PREV_BUFFER; i++) {
codecBufDescList.Current = (uint32_t)CODEC_BASE;
codecBufDescList.Control = ISI_DMA_C_CTRL_C_FETCH | ISI_DMA_C_CTRL_C_WB;
codecBufDescList.Next = (uint32_t)&codecBufDescList[ i + 1];
}
/* Wrapping to first FBD */
codecBufDescList[i-1].Next = (uint32_t)&codecBufDescList[0];
}

/**
* \brief TWI initilization.
*/
static void _twiInit(void)
{
/* Configure TWI pins. */
PIO_Configure(pinsTWI, PIO_LISTSIZE(pinsTWI));
/* Enable TWI peripheral clock */
PMC_EnablePeripheral(BOARD_ID_TWI_ISI);
/* Configure TWI */
TWI_ConfigureMaster(BOARD_BASE_TWI_ISI, TWCK, BOARD_MCK);
TWID_Initialize(&twid, BOARD_BASE_TWI_ISI);

/* Configure TWI interrupts */
IRQ_ConfigureIT(BOARD_ID_TWI_ISI, 0, TWI1_IrqHandler);
IRQ_EnableIT(BOARD_ID_TWI_ISI);
}

/**
* \brief ISI PCK initilization.
*/
static void _isiPckInit(void)
{
/* Configure ISI pins. */
PIO_Configure(pPinsISI, PIO_LISTSIZE(pPinsISI));
PIO_Configure(&pin_ISI_RSTN, 1);
/* Configure PCK as peripheral */
PIO_Configure(&pinPCK, 1);

/* Disable programmable clock 1 output */
REG_PMC_SCDR = PMC_SCER_PCK1;
/* Enable the DAC master clock */
PMC->PMC_PCK[1] = PMC_PCK_CSS_MCK_CLK | PMC_PCK_PRES_CLOCK_DIV8;
/* Enable programmable clock 1 output */
REG_PMC_SCER = PMC_SCER_PCK1;
/* Wait for the PCKRDY1 bit to be set in the PMC_SR register*/
while ((REG_PMC_SR & PMC_SR_PCKRDY1) == 0);
/* ISI PWD OFF*/
PIO_Clear(&pin_ISI_RSTN);
}

/**
* \brief ISI initilization.
*/
static void _isiInit(void)
{
/* LCD Frame Buffer Address */
sVideo.lcd_fb_addr = (uint32_t)ISI_BASE;
/* Base address for the frame buffer descriptors list */
sVideo.Isi_fbd_base = (uint32_t)&preBufDescList[0];
/* Start of Line */
sVideo.Hblank = 0;
/* Start of frame Delay */
sVideo.Vblank = 0;

/* Horizontal size of the Image sensor [0..2047] */
sVideo.codec_hsize = (ov_test[sensorType][formatIdx]).width;
/* Vertical size of the Image sensor [0..2047] */
sVideo.codec_vsize = (ov_test[sensorType][formatIdx]).height;
if (sVideo.codec_hsize > 640 || sVideo.codec_vsize > 480){
sVideo.lcd_hsize = 640;
sVideo.lcd_vsize = 480;
}
else {
sVideo.lcd_hsize = sVideo.codec_hsize;
sVideo.lcd_vsize = sVideo.codec_vsize;
}

/* Base address for codec DMA */
sVideo.codec_fb_addr = (uint32_t)CODEC_BASE;
/* Base address for the frame buffer descriptors list */
sVideo.codec_fbd_base = (uint32_t)&codecBufDescList[0];

/* Type of video */
sVideo.rgb_or_yuv = YUV;

ISI_Init(&sVideo);
ov_configure(&twid, sensorType, sVideo.codec_hsize, sVideo.codec_vsize);
#if defined (OV5640_AFC)
if (sensorType == OV_5640 && !afDone){
printf("Waiting for AF firmware download...\n\r");
ov_5640Afc_Firmware(&twid);
isOV5640_AF_InitDone(&twid);
afDone = 1;
}
#endif
}

/*----------------------------------------------------------------------------
* Global functions
*----------------------------------------------------------------------------*/

/**
* \brief Application entry point for TWI eeprom example.
*
* \return Unused (ANSI-C compatibility).
*/
extern int main( void )
{
uint8_t key;
volatile uint32_t delay;

WDT_Disable( WDT ) ;

/* Output example information */
printf( "-- ISI Example %s --\n\r", SOFTPACK_VERSION ) ;
printf( "-- %s\n\r", BOARD_NAME ) ;
printf( "-- Compiled: %s %s --\n\r", __DATE__, __TIME__ ) ;

/* LCD Initialize */
_lcdInit();
/* TWI Initialize */
_twiInit();
/* ISI PCK clock Initialize */
_isiPckInit();

sensorType = ov_init(&twid);
switch(sensorType) {
case OV_2640:
printf("-I- Omnivision 2640 detected \n\r");
break;
case OV_7740:
printf("-I- Omnivision 7740 detected \n\r");
break;
case OV_9740:
printf("-I- Omnivision 9740 detected \n\r");
break;
case OV_2643:
printf("-I- Omnivision 2643 detected \n\r");
break;
case OV_5640:
printf("-I- Omnivision 5640 detected \n\r");
break;
case OV_UNKNOWN:
printf("-E- Sensor can not be detected or supported! \n\r");
return 0;
}
_isiAllocateFBD();
ISI_Reset();
/* Enable ISI peripheral clock */
PMC_EnablePeripheral(ID_ISI);
ISI_DisableInterrupt(0xFFFFFFFF);
/* ISI Initialize */
formatIdx = 0;
_isiInit();
ISI_Reset();
ISI_Enable();

printf("-I- Press 'C' to capture image, press 'P' back to preview mode \n\r");
printf("-I- Press 'S' to change format (ov2643/ov5640/ov9740) \n\r");
for(;;) {
key = DBGU_GetChar();
switch(key) {
case 'c': case 'C':
printf("Capture image from CODEC path in YUV mode\n\r");
LCDC->LCDC_OVR1CHDR = LCDC_OVR1CHDR_CHDIS;
ISI->ISI_DMA_CHDR |= ISI_DMA_CHDR_P_CH_DIS;
ISI->ISI_DMA_CHER |= ISI_DMA_CHER_C_CH_EN;
for (delay = 0; delay < 0xffff; delay++);
ISI->ISI_CR |= ISI_CR_ISI_CDC;
while(( ISI->ISI_SR & ISI_SR_CDC_PND) != ISI_SR_CDC_PND);
while(( ISI->ISI_SR & ISI_SR_CXFR_DONE) != ISI_SR_CXFR_DONE);
printf("-I- Capture done \r\n");
for (delay = 0; delay < 0x5ffff; delay++);
LCDD_ShowBMPRotated(LCDD_HEO, NULL, 16, 0, 0, 640,480,
sVideo.codec_hsize, sVideo.codec_vsize,0);
LCDC->LCDC_HEOCHER = LCDC_HEOCHER_CHEN;
break;
case 'p': case 'P':
printf("preivew in RGB 565 mode\n\r");
ISI->ISI_DMA_CHDR |= ISI_DMA_CHDR_C_CH_DIS;
ISI->ISI_DMA_CHER |= ISI_DMA_CHER_P_CH_EN;
LCDC->LCDC_OVR1CHER = LCDC_OVR1CHER_CHEN;
LCDC->LCDC_HEOCHDR = LCDC_HEOCHDR_CHDIS;
break;
case 's': case 'S':
if ((REG_ISI_DMA_CHSR & ISI_DMA_CHSR_P_CH_S) != ISI_DMA_CHSR_P_CH_S)
{
ISI->ISI_DMA_CHDR |= ISI_DMA_CHDR_C_CH_DIS;
ISI->ISI_DMA_CHER |= ISI_DMA_CHER_P_CH_EN;
LCDC->LCDC_HEOCHDR = LCDC_HEOCHDR_CHDIS;
}
formatIdx = (formatIdx == 0)? 1: 0;
LCDC->LCDC_OVR1CHDR = LCDC_OVR1CHDR_CHDIS;
ISI_Disable();
_isiInit();
ISI_Reset();
ISI_Enable();
ISI->ISI_DMA_CHER |= ISI_DMA_CHER_P_CH_EN;
LCDC->LCDC_OVR1CHER = LCDC_OVR1CHER_CHEN;
break;
#if defined (OV5640_AFC)
case 'f':
printf("Single Focus\n\r");
ov_5640_AF_single(&twid);
break;
case 'F':
printf("Continue Auto Focus\n\r");
ov_5640_AF_continue(&twid);
break;
case 'X':
printf("Pause Auto Focus\n\r");
ov_5640_AFPause(&twid);
break;
case 'r': case 'R':
ov_5640_AFrelease(&twid);
break;
#endif
}
}
}

Return to “SAMA5D Cortex-A5 MPU”

Who is online

Users browsing this forum: No registered users and 1 guest