2013-09-16 07:35 PM
Hello All,
I've been working with the ov2640 example. I'm 95% sure I can get QQVGA out of the camera just fine; however, when I run through the registers for Jpeg I never get anything sensible out of the camera. I've tried toggling all of the clock signals and I've tried with jpeg on and off. I've even tried the registers from the ArduCam. Sometimes I get a lot of 0,1,2,3 data or 11,12,13 data but I never see any data that looks anything like jpeg. In the example ov2460 they dont ever actually use the jpeg modes since they were outputting directly to the lcd. I watch the dma2_stream1 ndtr register after the dcmi operation returns a frame int. With one setting of clocks I get about 8k of data used in the dma, but is all zeros when I look at the data. Most/all other settings I get all of the dma data (ntdr=0) or no bytes used in dma. When it uses all the bytes its garbage data, so I think I'm just enabling the clocks when I should not, getting garbage data (as I should). Any pointers are much appreciated ! If I can get jpeg data from this camera it will be the start of something wonderful !/**
* @brief Initializes the hardware resources (I2C and GPIO) used to configure
* the OV2640 camera.
* @param None
* @retval None
*/
void OV2640_HW_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStruct;
/*** Configures the DCMI GPIOs to interface with the OV2640 camera module ***/
/* Enable DCMI GPIOs clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE, ENABLE);
/* Connect DCMI pins to AF13 ************************************************/
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);//HSYNC
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);//PCLK
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);//VSYNC
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI);
/* DCMI GPIO configuration **************************************************/
/*
D0 -- PC6
D1 -- PC7
D2 -- PE0
D3 -- PE1
D4 -- PE4
D5 -- PB6
D6 -- PB8
D7 -- PB9
PCK - PA6
HS -- PA4
VS -- PB7
XCLK -- PA8 // mc0 driven
Y1,Y0 Not connected
RST -- PC12 // active low
PWDN -- PC10 // active hi
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* PCLK(PA6) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// setup the pwdn and rst pins
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 |GPIO_Pin_12;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// pdwn set low to disable (active high)
GPIO_ResetBits(GPIOC, GPIO_Pin_10);
// rst low to reset for 200 ms
GPIO_ResetBits(GPIOC, GPIO_Pin_12);
Delay(200);
// rst high to disable (active low)
GPIO_SetBits(GPIOC, GPIO_Pin_12);
// should be running now !
/****** Configures the I2C2 used for OV2640 camera module configuration *****/
/* I2C2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
/* Connect I2C2 pins to AF4 */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2);
/* Configure I2C2 GPIOs */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure I2C2 */
/* I2C DeInit */
I2C_DeInit(I2C2);
/* Enable the I2C peripheral */
I2C_Cmd(I2C2, ENABLE);
/* Set the I2C structure parameters */
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0xFE;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_ClockSpeed = 30000;
/* Initialize the I2C peripheral w/ selected parameters */
I2C_Init(I2C2, &I2C_InitStruct);
// start pa8 to drive the camera clock
MCO1_Init();
}
void OV2640_Init(ImageFormat_TypeDef ImageFormat)
{
DCMI_InitTypeDef DCMI_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/*** Configures the DCMI to interface with the OV2640 camera module ***/
/* Enable DCMI clock */
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
/* DCMI configuration */
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Embedded;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
// check for jpeg, assume jpg if not the two bmp formats
if(ImageFormat != BMP_QQVGA && ImageFormat != BMP_QVGA)
{
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low;
}
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_Init(&DCMI_InitStructure);
// check for jpeg, assume jpg if not the two bmp formats
if(ImageFormat != BMP_QQVGA && ImageFormat != BMP_QVGA)
{
DCMI_JPEGCmd(ENABLE);
}
//
/* DCMI Interrupts config ***************************************************/
DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE);
DCMI_ITConfig(DCMI_IT_LINE, ENABLE);
DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);
DCMI_ITConfig(DCMI_IT_ERR, ENABLE);
DCMI_ITConfig(DCMI_IT_OVF, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Configures the DMA2 to transfer Data from DCMI */
/* Enable DMA2 clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* DMA2 Stream1 Configuration */
DMA_DeInit(DMA2_Stream1);
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)frame_bufferA;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = sizeof(frame_bufferA) / sizeof(u32); // since it is doing it in 32 bit words
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word; // this was half word i think ?
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
/* DMA2 IRQ channel Configuration */
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
}
void OV2640_TakePic(ImageFormat_TypeDef ImageFormat)
{
OV2640_Init(ImageFormat);
// start dma and dcmi
DMA_Cmd(DMA2_Stream1, ENABLE);
DCMI_Cmd(ENABLE);
Delay(200);
// start the capture !
DCMI_CaptureCmd(ENABLE);
}
#ov2640-one-frame-photo
2013-09-17 08:44 AM
I thought I would familiarize myself with the regesters to get a better handle on this issue. Looking through them in the ov2640 DCMI example there are hundreds of them ! Then looking through the datasheet for the ov2640 half of the registers being initialized in the example code are listed as ''reserved'' even in the latest version of the datasheet I could find.
I think it has to be one of the registers are not configured correctly, but without knowing the registers in detail and in order the chances of me getting this to work is very low. This is all assuming jpeg worked in the dcmi example from ST to begin with, which could be wrong. Maybe I should be contacting OmniVision ? I'm going to search around for other registers to see if maybe I can find a combination that gives a different output. My question to y'all is: As far as DCMI -> dma is concerned there is nothing else for me to do right ? Once you set it up if you have the correct polarities and you have set up the perph correctly it should work. I was looking at hardware syncro vs the indicators I dont know if I should be using that or something. Does ST have any examples with jpeg so I can ensure at least my dcmi->dma is correct ?2013-09-17 09:12 AM
I'm lurking as these cameras really aren't my thing, and I don't have any boards with them attached.
I looked over the ST JPEG example, and it doesn't look unreasonable, although the resolution does look lame. I'm not sure what other plumbing is required, or how much ST tested or demoed the code. Not sure what support OV has, guess I'd fish for some of the configuration constants online, and double check that the JPEG data uses the same data lines, clocks, etc.2013-09-17 10:16 AM
Thanks for responding Clive.
I looked at examples by arducam and even tried them also (porting the registers to my code). But I didnt see anything but 0x00's. Ill search around for more drivers, there is a bunch of linux drivers and see their code so I can compare the registers. If anyone has regs that work for jpeg let me know, you can email them to me. If not my plan 'c' is going to be getting a arducam and reveng it to find out how it works and why mine does not.2013-09-17 01:39 PM
2013-09-17 02:35 PM
Wow, Thanks Clive, dono where you found those I'll read over them !
2013-09-18 06:31 PM
I read both of those manuals that I had not seen before. I also searched through all the drivers I could find and compared the registers. I also translated a few Chinese pages on other forums that seemed to be further along then me.
My best guess was that I had issues with the timing. I was really confused and didnt know if I should be setting the camera in capture mode or something. These cameras are pretty damn complicated. I really studied the arducam registers and how they used the fifo chip and the order in which they do things. The only differences between most of the registers was the ''digital video port'' speed. So I changed the arducam regs (0xd3,0x7f) and I made the MCO1 that I am using to drive the clock pllclk/5. I have sense changed the 0xD3 back to what arducam regs were which was 0. The data I get in my buffer seems almost right. I get about 8k used from my dma transfer. The data all seems like the first 4bits are correct and the second four are not. For example i get F0,D3,F0 in the start of my data. I also see several Fx,Dx portions of the data. In the jpeg standard the markers are FF,Dx or FF,Ex. So I think I'm really close to getting the correct data, there is some sort of slew or my pins are not working correctly or something (i think). Really the only thing I did to go from data that was all 0x00's to something that at least looks like it could be data is change my mco output so it was slower. I think maybe I was sending the camera a signal too fast. Does anyone know how I could get a 24Mhz signal out of the MCO ? I get I've got pll divided by 5 but how do i know the speed of pll. I'm pretty sure my external clock is 8 mhz and my cpu is running at 168mhz/**
* @brief Set PA8 Output SYSCLK/2.
* @param None
* @retval None
*/
void
MCO1_Init(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_ClockSecuritySystemCmd(ENABLE);
/* Enable GPIOs clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_MCO);
/* Configure MCO (PA8) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_5);
}
2013-09-18 07:30 PM
I looked at the data a little closer and this is what I found.
so, F3, D0 where we expect FF,D8
FF = 11111111
F3 = 11110011
D8 = 11011000
D0 = 11010000
thats D2 and D3 only which are PE0 and PE1
When I look at the schematic for the stm32f4 i see pe0 and pe1 are connected to a LIS302DL ''MEMS'' int1 and 2. I think those could be corrupting my data. The expansion board ''Open407V-D'' uses those pins by default for the camera module. I dont really get why they would use those pins if they were automatically going to be also attached to the ic on the discovery board. I dont think there is a way to disconnect them unless I can interfase with the ''mems'' and have those int lines go hiZ. But this is all assumptions. The Open407V-D will allow me to use C8 and C9 if i change some solder jumpers on the bottom of the board. But i have to be sure i'm not muxing them into something else already. I'll pick up with that tomorrow, my eyes hurt. Let me know if you think i'm on the right path.2013-09-18 07:41 PM
2013-09-18 09:55 PM
The STM32F4DIS-BB also uses PE0/1, the Dragon407 I'll have to check.
There is PC8/9 and PH11/12 24 MHz, you could use one of the TIM units to divide down 168 MHz, or use PA8 and run the system at 120 MHz (24 * 5), you could also perhaps run the I2SPLL at some other speed and use MCO2