From bdfb2f7eb671bf3476708211d8f5bb9c9f5990d6 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 10 Dec 2013 09:10:39 -0600 Subject: [PATCH] More OV2640 initialization logic --- arch/arm/src/sama5/sam_twi.c | 4 +- configs/sama5d3x-ek/ov2640/defconfig | 8 +- configs/sama5d3x-ek/src/sam_ov2640.c | 158 ++++++-------------------- configs/sama5d3x-ek/src/sama5d3x-ek.h | 19 ++++ drivers/video/Kconfig | 6 - drivers/video/ov2640.c | 85 ++++---------- include/nuttx/video/ov2640.h | 87 ++++++++++++++ 7 files changed, 173 insertions(+), 194 deletions(-) create mode 100644 include/nuttx/video/ov2640.h diff --git a/arch/arm/src/sama5/sam_twi.c b/arch/arm/src/sama5/sam_twi.c index 6d62aea1ec..beb16e51b8 100644 --- a/arch/arm/src/sama5/sam_twi.c +++ b/arch/arm/src/sama5/sam_twi.c @@ -190,7 +190,7 @@ static inline void twi_putrel(struct twi_dev_s *priv, unsigned int offset, /* I2C transfer helper functions */ static int twi_wait(struct twi_dev_s *priv); -static int twi_wakeup(struct twi_dev_s *priv, int result); +static void twi_wakeup(struct twi_dev_s *priv, int result); static int twi_interrupt(struct twi_dev_s *priv); #ifdef CONFIG_SAMA5_TWI0 static int twi0_interrupt(int irq, FAR void *context); @@ -473,7 +473,7 @@ static int twi_wait(struct twi_dev_s *priv) * *******************************************************************************/ -static int twi_wakeup(struct twi_dev_s *priv, int result) +static void twi_wakeup(struct twi_dev_s *priv, int result) { /* Cancel any pending timeout */ diff --git a/configs/sama5d3x-ek/ov2640/defconfig b/configs/sama5d3x-ek/ov2640/defconfig index 21bcaa9dc3..80d5f43182 100644 --- a/configs/sama5d3x-ek/ov2640/defconfig +++ b/configs/sama5d3x-ek/ov2640/defconfig @@ -144,7 +144,7 @@ CONFIG_SAMA5_USART1=y # CONFIG_SAMA5_USART2 is not set # CONFIG_SAMA5_USART3 is not set # CONFIG_SAMA5_TWI0 is not set -# CONFIG_SAMA5_TWI1 is not set +CONFIG_SAMA5_TWI1=y # CONFIG_SAMA5_TWI2 is not set # CONFIG_SAMA5_HSMCI0 is not set # CONFIG_SAMA5_HSMCI1 is not set @@ -203,6 +203,11 @@ CONFIG_SAMA5_LCDC_BASE_RGB565=y # CONFIG_SAMA5_LCDC_BASE_ARGB8888 is not set # CONFIG_SAMA5_LCDC_BASE_RGBA8888 is not set +# +# TWI device driver options +# +CONFIG_SAMA5_TWI1_FREQUENCY=100000 + # # External Memory Configuration # @@ -391,7 +396,6 @@ CONFIG_I2C_TRANSFER=y # CONFIG_AUDIO_DEVICES is not set CONFIG_VIDEO_DEVICES=y CONFIG_VIDEO_OV2640=y -# CONFIG_OV2640_MULTIPLE is not set CONFIG_OV2640_I2CADDR=0x21 CONFIG_OV2640_FREQUENCY=400000 CONFIG_OV2640_RGB565_COLORFMT=y diff --git a/configs/sama5d3x-ek/src/sam_ov2640.c b/configs/sama5d3x-ek/src/sam_ov2640.c index aa71ae79e5..4a5cc2c788 100644 --- a/configs/sama5d3x-ek/src/sam_ov2640.c +++ b/configs/sama5d3x-ek/src/sam_ov2640.c @@ -42,8 +42,9 @@ #include #include +#include #include -#include +#include #include "up_arch.h" @@ -52,7 +53,7 @@ #include "sam_pck.h" #include "sama5d3x-ek.h" -#if defined(CONFIG_SAMA5_ISI) && defined(CONFIG_SAMA5_OV2640_DEMO) +#ifdef HAVE_CAMERA /**************************************************************************** * Definitions @@ -63,10 +64,6 @@ * Private Data ****************************************************************************/ -/* The connection handler */ - -static NXHANDLE g_hnx = NULL; - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -75,120 +72,28 @@ static NXHANDLE g_hnx = NULL; * Name: ov2640_lcd_initialize ****************************************************************************/ -#ifndef CONFIG_NX_MULTIUSER -static inline int ov2640_lcd_initialize(void) +static inline FAR struct fb_vtable_s *ov2640_lcd_initialize(void) { - FAR NX_DRIVERTYPE *dev; + FAR struct fb_vtable_s *vplane; int ret; /* Initialize the frame buffer device */ - gvdbg("Initializing framebuffer\n"); ret = up_fbinitialize(); if (ret < 0) { gdbg("ERROR: up_fbinitialize failed: %d\n", -ret); - return EXIT_FAILURE; + return NULL; } - dev = up_fbgetvplane(0); - if (!dev) + vplane = up_fbgetvplane(0); + if (!vplane) { gdbg("ERROR: up_fbgetvplane failed\n"); - return EXIT_FAILURE; } - /* Then open NX */ - - gvdbg("Open NX\n"); - g_hnx = nx_open(dev); - if (!g_hnx) - { - gdbg("ERROR: nx_open failed: %d\n", errno); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + return vplane; } -#endif - -#ifdef CONFIG_NX_MULTIUSER -static inline int ov2640_lcd_initialize(void) -{ - struct sched_param param; - pthread_t thread; - pid_t servrid; - int ret; - - /* Set the client task priority */ - - param.sched_priority = CONFIG_EXAMPLES_NX_CLIENTPRIO; - ret = sched_setparam(0, ¶m); - if (ret < 0) - { - gdbg("ERROR: sched_setparam failed: %d\n" , ret); - return EXIT_FAILURE; - } - - /* Start the server task */ - - gvdbg("Starting nx_servertask task\n"); - servrid = task_create("NX Server", CONFIG_EXAMPLES_NX_SERVERPRIO, - CONFIG_EXAMPLES_NX_STACKSIZE, nx_servertask, NULL); - if (servrid < 0) - { - gdbg("ERROR: Failed to create nx_servertask task: %d\n", errno); - return EXIT_FAILURE; - } - - /* Wait a bit to let the server get started */ - - sleep(1); - - /* Connect to the server */ - - g_hnx = nx_connect(); - if (g_hnx) - { - pthread_attr_t attr; - - /* Start a separate thread to listen for server events. This is probably - * the least efficient way to do this, but it makes this example flow more - * smoothly. - */ - - (void)pthread_attr_init(&attr); - param.sched_priority = CONFIG_EXAMPLES_NX_LISTENERPRIO; - (void)pthread_attr_setschedparam(&attr, ¶m); - (void)pthread_attr_setstacksize(&attr, CONFIG_EXAMPLES_NX_STACKSIZE); - - ret = pthread_create(&thread, &attr, nx_listenerthread, NULL); - if (ret != 0) - { - printf("pthread_create failed: %d\n", ret); - return EXIT_FAILURE; - } - - /* Don't return until we are connected to the server */ - - while (!g_connected) - { - /* Wait for the listener thread to wake us up when we really - * are connected. - */ - - (void)sem_wait(&g_semevent); - } - } - else - { - gdbg("ERROR: nx_connect failed: %d\n", errno); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} -#endif /**************************************************************************** * Name: ov2640_camera_initialize @@ -196,11 +101,33 @@ static inline int ov2640_lcd_initialize(void) static inline int ov2640_camera_initialize(void) { + FAR struct i2c_dev_s *i2c; + int ret; + + /* Get the I2C driver that interfaces with the camers (OV2640_BUS)*/ + + i2c = up_i2cinitialize(OV2640_BUS); + if (!i2c) + { + fdbg("ERROR: Failed to initialize TWI%d\n", OV2640_BUS); + return EXIT_FAILURE; + } + /* Enable clocking to the ISI peripheral */ sam_isi_enableclk(); #warning Missing Logic + + /* Initialize the OV2640 camera */ + + ret = ov2640_initialize(i2c); + if (ret < 0) + { + fdbg("ERROR: Failed to initialize the OV2640: %d\n", ret); + return EXIT_FAILURE; + } + return EXIT_FAILURE; } @@ -218,12 +145,13 @@ static inline int ov2640_camera_initialize(void) int ov2640_main(int argc, char *argv[]) { + FAR struct fb_vtable_s *vplane; int ret; /* First, initialize the display */ - ret = ov2640_lcd_initialize(); - if (ret != EXIT_SUCCESS) + vplane = ov2640_lcd_initialize(); + if (!vplane) { gdbg("ERROR: ov2640_lcd_initialize failed\n"); return EXIT_FAILURE; @@ -235,24 +163,10 @@ int ov2640_main(int argc, char *argv[]) if (ret != EXIT_SUCCESS) { gdbg("ERROR: ov2640_camera_initialize failed\n"); - goto errout_with_nx; + return EXIT_FAILURE; } return EXIT_SUCCESS; - -errout_with_nx: -#ifdef CONFIG_NX_MULTIUSER - /* Disconnect from the server */ - - gvdbg("Disconnect from the server\n"); - nx_disconnect(g_hnx); -#else - /* Close the server */ - - gvdbg("Close NX\n"); - nx_close(g_hnx); -#endif - return EXIT_FAILURE; } -#endif /* CONFIG_SAMA5_ISI && CONFIG_SAMA5_OV2640_DEMO */ +#endif /* HAVE_CAMERA */ diff --git a/configs/sama5d3x-ek/src/sama5d3x-ek.h b/configs/sama5d3x-ek/src/sama5d3x-ek.h index 57d27ef4c2..3273c3b25d 100644 --- a/configs/sama5d3x-ek/src/sama5d3x-ek.h +++ b/configs/sama5d3x-ek/src/sama5d3x-ek.h @@ -63,6 +63,7 @@ #define HAVE_USBDEV 1 #define HAVE_USBMONITOR 1 #define HAVE_NETWORK 1 +#define HAVE_CAMERA 1 /* HSMCI */ /* Can't support MMC/SD if the card interface(s) are not enable */ @@ -317,6 +318,24 @@ # undef HAVE_NETWORK #endif +/* Camera */ + +#define OV2640_BUS 1 + +#ifndef CONFIG_SAMA5_OV2640_DEMO +# undef HAVE_CAMERA +#endif + +#if defined(HAVE_CAMERA) && !defined(CONFIG_SAMA5_ISI) +# warning OV2640 camera demo requires CONFIG_SAMA5_ISI +# undef HAVE_CAMERA +#endif + +#if defined(HAVE_CAMERA) && !defined(CONFIG_SAMA5_TWI1) +# warning OV2640 camera demo requires CONFIG_SAMA5_TWI1 +# undef HAVE_CAMERA +#endif + /* LEDs *****************************************************************************/ /* There are two LEDs on the SAMA5D3 series-CM board that can be controlled * by software. A blue LED is controlled via PIO pins. A red LED normally diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index ebd06046b5..4e09d32e0e 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -10,12 +10,6 @@ config VIDEO_OV2640 if VIDEO_OV2640 -config OV2640_MULTIPLE - bool "Multiple OV2640 devices" - default n - ---help--- - Build in support for multiple on-board OV2640 devices - config OV2640_I2CADDR hex "I2C address (7-bit)" default 0x21 diff --git a/drivers/video/ov2640.c b/drivers/video/ov2640.c index 29861fb8cc..ed611189d6 100644 --- a/drivers/video/ov2640.c +++ b/drivers/video/ov2640.c @@ -54,6 +54,7 @@ #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -268,11 +269,6 @@ struct ovr2640_reg_s }; #define ARRAY_NENTRIES(a) (sizeof(a)/sizeof(struct ovr2640_reg_s)) -struct ov2640_dev_s -{ - struct i2c_dev_s *i2c; -}; - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -297,10 +293,6 @@ static int ov2640_reset(FAR struct i2c_dev_s *i2c); * Private Data ****************************************************************************/ -#ifndef CONFIG_OV2640_MULTIPLE -static struct ov2640_dev_s g_ov2640; -#endif - /* OV2640 reset */ static const struct ovr2640_reg_s g_ov2640_reset[] = @@ -892,47 +884,21 @@ static int ov2640_reset(FAR struct i2c_dev_s *i2c) * Function: ov2640_initialize * * Description: - * Initialize the OV2640. + * Initialize the OV2640 camera. * * Parameters: * i2c - Reference to the I2C driver structure * * Returned Value: - * On success, a non-NULL reference tot he ov2640 driver structure is - * returned; NULL is returned on any failure. + * Zero (OK) is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. * ****************************************************************************/ -FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) +int ov2640_initialize(FAR struct i2c_dev_s *i2c) { - FAR struct ov2640_dev_s *priv; int ret; -#ifdef CONFIG_OV2640_MULTIPLE - /* Allocate a new OV2640 device structure */ - - priv = (FAR struct ov2640_dev_s *)kmalloc(sizeof(struct ov2640_dev_s)); - if (!priv) - { - gdbg("ERROR: Failed to allocate OV2640 device structure\n"); - return -ENOMEM; - } - -#else /* CONFIG_OV2640_MULTIPLE */ - - /* There is only a single OV2640. Use the single, pre-allocated device - * structure - */ - - priv = &g_ov2640; - -#endif /* CONFIG_OV2640_MULTIPLE */ - - /* Initialize the OV2640 device structure */ - - memset(priv, 0, sizeof(struct ov2640_dev_s)); - priv->i2c = i2c; - /* Configure I2C bus for the OV2640 */ I2C_SETADDRESS(i2c, CONFIG_OV2640_FREQUENCY, 7); @@ -943,6 +909,7 @@ FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) ret = ov2640_reset(i2c); if (ret < 0) { + gdbg("ERROR: ov2640_reset failed: %d\n", ret); goto errout; } @@ -951,6 +918,7 @@ FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) ret = ovr2640_chipid(i2c); if (ret < 0) { + gdbg("ERROR: ovr2640_chipid failed: %d\n", ret); goto errout; } @@ -1040,7 +1008,7 @@ FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) /* Setup initial register values */ - ret = ov2640_putreglist(priv->i2c, g_ov2640_initialregs, + ret = ov2640_putreglist(i2c, g_ov2640_initialregs, OV2640_INITIALREGS_NENTRIES); if (ret < 0) { @@ -1050,7 +1018,7 @@ FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) /* Setup image resolution */ - ret = ov2640_putreglist(priv->i2c, g_ov2640_resolution_common, + ret = ov2640_putreglist(i2c, g_ov2640_resolution_common, OV2640_RESOLUTION_COMMON_NENTRIES); if (ret < 0) { @@ -1059,35 +1027,35 @@ FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) } #if defined(CONFIG_OV2640_QCIF_RESOLUTION) - ret = ov2640_putreglist(priv->i2c, g_ov2640_qcif_resolution, + ret = ov2640_putreglist(i2c, g_ov2640_qcif_resolution, OV2640_QCIF_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_QVGA_RESOLUTION) - ret = ov2640_putreglist(priv->i2c, g_ov2640_qvga_resolution, + ret = ov2640_putreglist(i2c, g_ov2640_qvga_resolution, OV2640_QVGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_CIF_RESOLUTION) - ret = ov2640_putreglist(priv->i2c, g_ov2640_cif_resolution, + ret = ov2640_putreglist(i2c, g_ov2640_cif_resolution, OV2640_CIF_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_VGA_RESOLUTION) - ret = ov2640_putreglist(priv->i2c, g_ov2640_vga_resolution, + ret = ov2640_putreglist(i2c, g_ov2640_vga_resolution, OV2640_VGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_SVGA_RESOLUTION) - ret = ov2640_putreglist(priv->i2c, g_ov2640_svga_resolution, + ret = ov2640_putreglist(i2c, g_ov2640_svga_resolution, OV2640_SVGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_XGA_RESOLUTION) - ret = ov2640_putreglist(priv->i2c, g_ov2640_xga_resolution, + ret = ov2640_putreglist(i2c, g_ov2640_xga_resolution, OV2640_XGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_SXGA_RESOLUTION) - ret = ov2640_putreglist(priv->i2c, g_ov2640_sxga_resolution, + ret = ov2640_putreglist(i2c, g_ov2640_sxga_resolution, OV2640_SXGA_RESOLUTION_NENTRIES); #elif defined(CONFIG_OV2640_UXGA_RESOLUTION) - ret = ov2640_putreglist(priv->i2c, g_ov2640_uxga_resolution, + ret = ov2640_putreglist(i2c, g_ov2640_uxga_resolution, OV2640_UXGA_RESOLUTION_NENTRIES); #else @@ -1102,7 +1070,7 @@ FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) /* Color format register settings */ - ret = ov2640_putreglist(priv->i2c, g_ov2640_colorfmt_common, + ret = ov2640_putreglist(i2c, g_ov2640_colorfmt_common, OV2640_COLORFMT_COMMON_NENTRIES); if (ret < 0) { @@ -1111,11 +1079,11 @@ FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) } #if defined(CONFIG_OV2640_YUV422_COLORFMT) - ret = ov2640_putreglist(priv->i2c, g_ov2640_yuv422_colorfmt, + ret = ov2640_putreglist(i2c, g_ov2640_yuv422_colorfmt, OV2640_YUV422_COLORFMT_NENTRIES); #elif defined(CONFIG_OV2640_RGB565_COLORFMT) - ret = ov2640_putreglist(priv->i2c, g_ov2640_rgb565_colorfmt, + ret = ov2640_putreglist(i2c, g_ov2640_rgb565_colorfmt, OV2640_RGB565_COLORFMT_NENTRIES); #else @@ -1128,19 +1096,12 @@ FAR struct ov2640_dev_s *ov2640_initialize(struct i2c_dev_s *i2c) goto errout; } - return OK; - #endif /* CONFIG_OV2640_JPEG */ - return priv; + return OK; errout: - gdbg("ERROR: Failed to intialize the OV2640: %d\n", ret); - -#ifdef CONFIG_OV2640_MULTIPLE - kfree(priv); -#endif /* CONFIG_OV2640_MULTIPLE */ - + gdbg("ERROR: Failed to initialize the OV2640: %d\n", ret); (void)ov2640_reset(i2c); - return NULL; + return ret; } diff --git a/include/nuttx/video/ov2640.h b/include/nuttx/video/ov2640.h new file mode 100644 index 0000000000..eb9fa3ed69 --- /dev/null +++ b/include/nuttx/video/ov2640.h @@ -0,0 +1,87 @@ +/**************************************************************************** + * include/nuttx/video/ov2640.h + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name NuttX 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_VIDEO_OV2640_H +#define __INCLUDE_NUTTX_VIDEO_OV2640_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Function: ov2640_initialize + * + * Description: + * Initialize the OV2640 camera. + * + * Parameters: + * i2c - Reference to the I2C driver structure + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +struct i2c_dev_s; +int ov2640_initialize(FAR struct i2c_dev_s *i2c); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_VIDEO_OV2640_H */