📄 pxa_camera-hzh.c
字号:
// parameter check if (camera_context->buffer_virtual == NULL || camera_context->buffer_physical == NULL || camera_context->buf_size == 0) return STATUS_WRONG_PARAMETER; if (camera_context->dma_descriptors_virtual == NULL || camera_context->dma_descriptors_physical == NULL || camera_context->dma_descriptors_size == 0) return STATUS_WRONG_PARAMETER; if (camera_context->sensor_type > CAMERA_TYPE_MAX) return STATUS_WRONG_PARAMETER; if (camera_context->capture_input_format > CAMERA_IMAGE_FORMAT_MAX || camera_context->capture_output_format > CAMERA_IMAGE_FORMAT_MAX) return STATUS_WRONG_PARAMETER; // check the function dispatch table according to the sensor type if ( !camera_context->camera_functions ) return STATUS_WRONG_PARAMETER; if ( !camera_context->camera_functions->init || !camera_context->camera_functions->deinit || !camera_context->camera_functions->set_capture_format || !camera_context->camera_functions->start_capture || !camera_context->camera_functions->stop_capture ) return STATUS_WRONG_PARAMETER; // init context status for(i=0; i<3; i++) camera_context->dma_channels[i] = 0xFF; (int)camera_context->fifo0_descriptors_virtual = NULL; (int)camera_context->fifo1_descriptors_virtual = NULL; (int)camera_context->fifo2_descriptors_virtual = NULL; (int)camera_context->fifo0_descriptors_physical = NULL; (int)camera_context->fifo1_descriptors_physical = NULL; (int)camera_context->fifo2_descriptors_physical = NULL; camera_context->fifo0_num_descriptors = 0; camera_context->fifo1_num_descriptors = 0; camera_context->fifo2_num_descriptors = 0; camera_context->fifo0_transfer_size = 0; camera_context->fifo1_transfer_size = 0; camera_context->fifo2_transfer_size = 0; camera_context->block_number = 0; camera_context->block_size = 0; camera_context->block_header = 0; camera_context->block_tail = 0; // Enable hardware camera_gpio_init(); // capture interface init ci_init(); // sensor init ret = camera_context->camera_functions->init(camera_context); if (ret) goto camera_init_err; camera_context->dma_channels[0] = ci_dma_y; camera_context->dma_channels[1] = ci_dma_cb; camera_context->dma_channels[2] = ci_dma_cr; // set capture format ret = camera_set_capture_format(camera_context); if (ret) goto camera_init_err; // set frame rate camera_set_capture_frame_rate(camera_context); return 0;camera_init_err: camera_deinit(camera_context); return -1; }void camera_gpio_init(){ pxa_gpio_mode( 27 | GPIO_ALT_FN_3_IN); /* CIF_DD[0] */ pxa_gpio_mode( 114 | GPIO_ALT_FN_1_IN); /* CIF_DD[1] */ pxa_gpio_mode( 116 | GPIO_ALT_FN_1_IN); /* CIF_DD[2] */ pxa_gpio_mode( 115 | GPIO_ALT_FN_2_IN); /* CIF_DD[3] */ pxa_gpio_mode( 90 | GPIO_ALT_FN_3_IN); /* CIF_DD[4] */ pxa_gpio_mode( 91 | GPIO_ALT_FN_3_IN); /* CIF_DD[5] */ pxa_gpio_mode( 17 | GPIO_ALT_FN_2_IN); /* CIF_DD[6] */ pxa_gpio_mode( 12 | GPIO_ALT_FN_2_IN); /* CIF_DD[7] */ pxa_gpio_mode( 23 | GPIO_ALT_FN_1_OUT); /* CIF_MCLK */ pxa_gpio_mode( 26 | GPIO_ALT_FN_2_IN); /* CIF_PCLK */ pxa_gpio_mode( 25 | GPIO_ALT_FN_1_IN); /* CIF_LV */ pxa_gpio_mode( 24 | GPIO_ALT_FN_1_IN); /* CIF_FV */#ifdef OV9640 pxa_gpio_mode( 120 | GPIO_OUT); /* CAMERA_PWR */#endif return;}int camera_deinit( p_camera_context_t camera_context ){ int ret; // deinit sensor ret = camera_context->camera_functions->deinit(camera_context); // capture interface deinit ci_deinit(); return ret;}/*********************************************************************** * * Capture APIs * ***********************************************************************/// Set the image formatint camera_set_capture_format( p_camera_context_t camera_context ){ int ret; unsigned int frame_size; unsigned int block_number = 0; CI_IMAGE_FORMAT ci_input_format, ci_output_format; CI_MP_TIMING timing; // set capture interface if (camera_context->capture_input_format > CAMERA_IMAGE_FORMAT_MAX || camera_context->capture_output_format > CAMERA_IMAGE_FORMAT_MAX ) return STATUS_WRONG_PARAMETER; ci_input_format = FORMAT_MAPPINGS[camera_context->capture_input_format]; ci_output_format = FORMAT_MAPPINGS[camera_context->capture_output_format]; if (ci_input_format == CI_INVALID_FORMAT || ci_output_format == CI_INVALID_FORMAT) return STATUS_WRONG_PARAMETER; ci_set_image_format(ci_input_format, ci_output_format); timing.BFW = timing.BLW = 0; ci_configure_mp(camera_context->capture_width-1, camera_context->capture_height-1, &timing); // set sensor setting ret = camera_context->camera_functions->set_capture_format(camera_context); if (ret) return ret; // ring buffer init switch(camera_context->capture_output_format) { case CAMERA_IMAGE_FORMAT_RGB565: frame_size = camera_context->capture_width * camera_context->capture_height * 2; camera_context->fifo0_transfer_size = frame_size; camera_context->fifo1_transfer_size = 0; camera_context->fifo2_transfer_size = 0; break; case CAMERA_IMAGE_FORMAT_YCBCR422_PACKED: frame_size = camera_context->capture_width * camera_context->capture_height * 2; camera_context->fifo0_transfer_size = frame_size; camera_context->fifo1_transfer_size = 0; camera_context->fifo2_transfer_size = 0; break; case CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR: frame_size = camera_context->capture_width * camera_context->capture_height * 2; camera_context->fifo0_transfer_size = frame_size / 2; //FIFO0(Y通道)DMA传送字节数 camera_context->fifo1_transfer_size = frame_size / 4; //FIFO0(Cb通道)DMA传送字节数 camera_context->fifo2_transfer_size = frame_size / 4; //FIFO0(Cr通道)DMA传送字节数 break; case CAMERA_IMAGE_FORMAT_RGB666_PLANAR: frame_size = camera_context->capture_width * camera_context->capture_height * 4; camera_context->fifo0_transfer_size = frame_size; camera_context->fifo1_transfer_size = 0; camera_context->fifo2_transfer_size = 0; break; case CAMERA_IMAGE_FORMAT_RGB666_PACKED: frame_size = camera_context->capture_width * camera_context->capture_height * 3; camera_context->fifo0_transfer_size = frame_size; camera_context->fifo1_transfer_size = 0; camera_context->fifo2_transfer_size = 0; break; case CAMERA_IMAGE_FORMAT_RGB888_PLANAR: frame_size = camera_context->capture_width * camera_context->capture_height * 4; camera_context->fifo0_transfer_size = frame_size; camera_context->fifo1_transfer_size = 0; camera_context->fifo2_transfer_size = 0; break; default: return STATUS_WRONG_PARAMETER; break; } camera_context->block_size = frame_size; block_number = camera_context->buf_size / frame_size; camera_context->block_number = block_number > MAX_BLOCK_NUM ? MAX_BLOCK_NUM : block_number; camera_context->block_header = camera_context->block_tail = 0; // generate dma descriptor chain ret = update_dma_chain(camera_context); if (ret) return -1; return 0;}// take a picture and copy it into the ring bufferint camera_capture_still_image( p_camera_context_t camera_context, unsigned int block_id ){ int status; // init buffer status & capture camera_context->block_header = camera_context->block_tail = block_id; camera_context->capture_status = 0; status = start_capture( camera_context, block_id, 1 ); return status;}// capture motion video and copy it to the ring bufferint camera_start_video_capture( p_camera_context_t camera_context, unsigned int block_id ){ int status; // init buffer status & capture camera_context->block_header = camera_context->block_tail = block_id; camera_context->capture_status = CAMERA_STATUS_VIDEO_CAPTURE_IN_PROCESS; status = start_capture( camera_context, block_id, 0 ); return status;}// disable motion video image capturevoid camera_stop_video_capture( p_camera_context_t camera_context ){ int status; // stop capture status = camera_context->camera_functions->stop_capture(camera_context); // stop dma stop_dma_transfer(camera_context); // update the flag if ( !(camera_context->capture_status & CAMERA_STATUS_RING_BUFFER_FULL) ) camera_context->capture_status &= ~CAMERA_STATUS_VIDEO_CAPTURE_IN_PROCESS; return;}/*********************************************************************** * * Flow Control APIs * ***********************************************************************/// continue capture image to next available buffervoid camera_continue_transfer( p_camera_context_t camera_context ){ // don't think we need this either. JR // continue transfer on next block start_dma_transfer( camera_context, camera_context->block_tail );}// Return 1: there is available buffer, 0: buffer is fullint camera_next_buffer_available( p_camera_context_t camera_context ){ camera_context->block_header = (camera_context->block_header + 1) % camera_context->block_number; if (((camera_context->block_header + 1) % camera_context->block_number) != camera_context->block_tail) { return 1; } camera_context->capture_status |= CAMERA_STATUS_RING_BUFFER_FULL; return 0;}// Application supplies the FrameBufferID to the driver to tell it that the application has completed processing of // the given frame buffer, and that buffer is now available for re-use.void camera_release_frame_buffer( p_camera_context_t camera_context, unsigned int frame_buffer_id ){ camera_context->block_tail = (camera_context->block_tail + 1) % camera_context->block_number; // restart video capture only if video capture is in progress and space is available for image capture if( (camera_context->capture_status & CAMERA_STATUS_RING_BUFFER_FULL ) && (camera_context->capture_status & CAMERA_STATUS_VIDEO_CAPTURE_IN_PROCESS)) { if (((camera_context->block_header + 2) % camera_context->block_number) != camera_context->block_tail) { camera_context->capture_status &= ~CAMERA_STATUS_RING_BUFFER_FULL; start_capture( camera_context, camera_context->block_tail, 0 ); } }}// Returns the FrameBufferID for the first filled frame// Note: -1 represents buffer emptyint camera_get_first_frame_buffer_id( p_camera_context_t camera_context ){ // check whether buffer is empty if ( (camera_context->block_header == camera_context->block_tail) && !(camera_context->capture_status & CAMERA_STATUS_RING_BUFFER_FULL) ) return -1; // return the block header return camera_context->block_header;}// Returns the FrameBufferID for the last filled frame, this would be used if we were polling for image completion data, // or we wanted to make sure there were no frames waiting for us to process.// Note: -1 represents buffer emptyint camera_get_last_frame_buffer_id( p_camera_context_t camera_context ){ int ret; // check whether buffer is empty if ( (camera_context->block_header == camera_context->block_tail) && !(camera_context->capture_status & CAMERA_STATUS_RING_BUFFER_FULL) ) return -1; // return the block before the block_tail ret = ( camera_context->block_tail + camera_context->block_number -1 ) % camera_context->block_number; return ret;}/*********************************************************************** * * Buffer Info APIs * ***********************************************************************/// Return: the number of frame buffers allocated for use.unsigned int camera_get_num_frame_buffers( p_camera_context_t camera_context ){ return camera_context->block_number;}// FrameBufferID is a number between 0 and N-1, where N is the total number of frame buffers in use. Returns the address of// the given frame buffer. The application will call this once for each frame buffer at application initialization only.void* camera_get_frame_buffer_addr( p_camera_context_t camera_context, unsigned int frame_buffer_id ){ return (void*)((unsigned)camera_context->buffer_virtual + camera_context->block_size * frame_buffer_id);}// Return the block idint camera_get_frame_buffer_id( p_camera_context_t camera_context, void* address ){ if ( ((unsigned)address >= (unsigned)camera_context->buffer_virtual) && ((unsigned)address <= (unsigned)camera_context->buffer_virtual + camera_context->buf_size )) return ((unsigned)address - (unsigned)camera_context->buffer_virtual) / camera_context->block_size; return -1;}/*********************************************************************** * * Frame rate APIs * ***********************************************************************/// Set desired frame ratevoid camera_set_capture_frame_rate( p_camera_context_t camera_context ){ ci_set_frame_rate(camera_context->frame_rate); return;} // return current settingvoid camera_get_capture_frame_rate( p_camera_context_t camera_context ){ camera_context->frame_rate = ci_get_frame_rate(); return;} /*********************************************************************** * * Interrupt APIs * ***********************************************************************/// set interrupt mask void camera_set_int_mask( p_camera_context_t camera_context, unsigned int mask ){ pxa_dma_desc *end_des_virtual; int dma_interrupt_on; unsigned int i; // set CI interrupt ci_set_int_mask( mask & CI_CICR0_INTERRUPT_MASK ); // set dma end interrupt if ( mask & CAMERA_INTMASK_END_OF_DMA ) dma_interrupt_on = 1; else dma_interrupt_on = 0; // set fifo0 dma chains' flag end_des_virtual = (pxa_dma_desc*)camera_context->fifo0_descriptors_virtual + camera_context->fifo0_num_descriptors - 1; for(i=0; i<camera_context->block_number; i++) { if (dma_interrupt_on)//如果使能DMA,在每块的最后一个传输描述符里使能结束中断 end_des_virtual->dcmd |= DCMD_ENDIRQEN; else end_des_virtual->dcmd &= ~DCMD_ENDIRQEN; end_des_virtual += camera_context->fifo0_num_descriptors; }} // get interrupt mask unsigned int camera_get_int_mask( p_camera_context_t camera_context ){ pxa_dma_desc *end_des_virtual; unsigned int ret; // get CI mask ret = ci_get_int_mask(); // get dma end mask end_des_virtual = (pxa_dma_desc *)camera_context->fifo0_descriptors_virtual + camera_context->fifo0_num_descriptors - 1; if (end_des_virtual->dcmd & DCMD_ENDIRQEN) ret |= CAMERA_INTMASK_END_OF_DMA; return ret; } // clear interrupt statusvoid camera_clear_int_status( p_camera_context_t camera_context, unsigned int status )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -