diff --git a/src/omv/Makefile b/src/omv/Makefile index 58d523abe..574791839 100644 --- a/src/omv/Makefile +++ b/src/omv/Makefile @@ -46,6 +46,7 @@ SRCS += $(addprefix sensors/, \ gc2145.c \ genx320.c \ pag7920.c \ + pag7936.c \ paj6100.c \ frogeye2020.c \ ) diff --git a/src/omv/common/sensor.h b/src/omv/common/sensor.h index 25ceec073..a07e1bbea 100644 --- a/src/omv/common/sensor.h +++ b/src/omv/common/sensor.h @@ -25,6 +25,7 @@ #define GENX320_SLV_ADDR (0x78) #define FROGEYE2020_SLV_ADDR (0x6E) #define PAG7920_SLV_ADDR (0x80) +#define PAG7936_SLV_ADDR (0x80) // Chip ID Registers #define OV5640_CHIP_ID (0x300A) @@ -33,7 +34,7 @@ #define HIMAX_CHIP_ID (0x0001) #define GC_CHIP_ID (0xF0) #define GENX320_CHIP_ID (0x0014) -#define PIXART_CHIP_ID (0x00) +#define PIXART_CHIP_ID (0x0000) // Chip ID Values #define OV2640_ID (0x26) @@ -62,6 +63,7 @@ #define GENX320_ID_ES (0x30501C01) #define GENX320_ID_MP (0xB0602003) #define PAG7920_ID (0x7920) +#define PAG7936_ID (0x7936) #define PAJ6100_ID (0x6100) #define FROGEYE2020_ID (0x2020) diff --git a/src/omv/common/sensor_utils.c b/src/omv/common/sensor_utils.c index 940508ee0..2de1534ec 100644 --- a/src/omv/common/sensor_utils.c +++ b/src/omv/common/sensor_utils.c @@ -27,6 +27,7 @@ #include "hm01b0.h" #include "hm0360.h" #include "pag7920.h" +#include "pag7936.h" #include "paj6100.h" #include "frogeye2020.h" #include "gc2145.h" @@ -255,10 +256,17 @@ static int sensor_detect() { #if (OMV_PAG7920_ENABLE == 1) case PAG7920_SLV_ADDR: - omv_i2c_readw(&sensor.i2c_bus, slv_addr, ON_CHIP_ID, (uint16_t *) &sensor.chip_id); - sensor.chip_id = (sensor.chip_id << 8) | (sensor.chip_id >> 8); + omv_i2c_readw2(&sensor.i2c_bus, slv_addr, PIXART_CHIP_ID, (uint16_t *) &sensor.chip_id); + sensor.chip_id = ((sensor.chip_id << 8) | (sensor.chip_id >> 8)) & 0xFFFF; return slv_addr; #endif // (OMV_PAG7920_ENABLE == 1) + + #if (OMV_PAG7936_ENABLE == 1) + case PAG7936_SLV_ADDR: + omv_i2c_readw2(&sensor.i2c_bus, slv_addr, PIXART_CHIP_ID, (uint16_t *) &sensor.chip_id); + sensor.chip_id = ((sensor.chip_id << 8) | (sensor.chip_id >> 8)) & 0xFFFF; + return slv_addr; + #endif // (OMV_PAG7936_ENABLE == 1) } } @@ -472,6 +480,15 @@ int sensor_probe_init(uint32_t bus_id, uint32_t bus_speed) { break; #endif // (OMV_PAG7920_ENABLE == 1) + #if (OMV_PAG7936_ENABLE == 1) + case PAG7936_ID: + if (sensor_set_xclk_frequency(OMV_PAG7936_XCLK_FREQ) != 0) { + return SENSOR_ERROR_TIM_INIT_FAILED; + } + init_ret = pag7936_init(&sensor); + break; + #endif // (OMV_PAG7936_ENABLE == 1) + #if (OMV_PAJ6100_ENABLE == 1) case PAJ6100_ID: if (sensor_set_xclk_frequency(OMV_PAJ6100_XCLK_FREQ) != 0) { diff --git a/src/omv/sensors/pag7936.c b/src/omv/sensors/pag7936.c new file mode 100644 index 000000000..ed0b632eb --- /dev/null +++ b/src/omv/sensors/pag7936.c @@ -0,0 +1,437 @@ +/* + * Copyright (C) 2023-2024 OpenMV, LLC. + * + * 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. Any redistribution, use, or modification in source or binary form + * is done solely for personal benefit and not for any commercial + * purpose or for monetary gain. For commercial licensing options, + * please contact openmv@openmv.io + * + * THIS SOFTWARE IS PROVIDED BY THE LICENSOR AND COPYRIGHT OWNER "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 LICENSOR OR COPYRIGHT + * OWNER 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. + * + * PixArt PAG7936 driver. + */ +#include "omv_boardconfig.h" +#if (OMV_PAG7936_ENABLE == 1) + +#include +#include +#include +#include + +#include "omv_i2c.h" +#include "sensor.h" +#include "pag7936.h" +#include "py/mphal.h" + +#define FRAME_TIME_20_16 (0x004E) +#define FRAME_TIME_15_8 (0x004D) +#define FRAME_TIME_7_0 (0x004C) +#define AGC_H (0x1424) +#define AGC_L (0x1423) +#define AE_EXPO_MANUAL_17_16 (0x1427) +#define AE_EXPO_MANUAL_15_8 (0x1426) +#define AE_EXPO_MANUAL_7_0 (0x1425) +#define SENSOR_UPDATE (0x00EB) +#define INTERFACE_POLARITY (0x0EAF) +#define SENSOR_OPMODE (0x0008) +#define SENSOR_TRIGGER_FRAMENUM (0x002E) +#define SENSOR_TRIGGER_EN (0x002F) +#define SENSOR_TG_EN (0x0030) +#define SENSOR_TRIGGER_MODE (0x0031) +#define SENSOR_SOFTWARE_TRIGGER (0x00EA) +#define ISP_WOI_EN (0x0E10) +#define ISP_WOI_HSIZE_L (0x0E11) +#define ISP_WOI_HSIZE_H (0x0E12) +#define ISP_WOI_VSIZE_L (0x0E13) +#define ISP_WOI_VSIZE_H (0x0E14) +#define ISP_WOI_HOFFSET_L (0x0E15) +#define ISP_WOI_HOFFSET_H (0x0E16) +#define ISP_WOI_VOFFSET_L (0x0E17) +#define ISP_WOI_VOFFSET_H (0x0E18) +#define TG_MONO_SENSOR (0x01BF) +#define TG_FLIP (0x01CE) +#define TG_FLIP_SET_VFLIP(r, x) ((r & 0xFB) | ((x & 1) << 2)) +#define TG_FLIP_SET_HFLIP(r, x) ((r & 0xF7) | ((x & 1) << 3)) +#define AVERAGE_MODE (0x01C0) +#define ROW_AVERAGE_MODE (0x0166) +#define COL_AVERAGE_MODE (0x016F) +#define HSIZE_L (0x01C6) +#define HSIZE_H (0x01C7) +#define VSIZE_L (0x01C8) +#define VSIZE_H (0x01C9) +#define WOI_HSIZE_L (0x0221) +#define WOI_HSIZE_H (0x0222) +#define WOI_VSIZE_L (0x0223) +#define WOI_VSIZE_H (0x0224) +#define WOI_HSTART_L (0x0225) +#define WOI_HSTART_H (0x0226) +#define WOI_VSTART_L (0x0227) +#define WOI_VSTART_H (0x0228) + +#define RGB_STAT_B_VS (0x04C9) +#define RGB_STAT_GB_VS (0x04CD) +#define RGB_STAT_R_VS (0x04D1) +#define RGB_STAT_GR_VS (0x04D5) + +#define FT_CLK (1000000) +#define FPS_MAX (120) // by sensor setting!! + +#define FMAX_720P_120_LINEAR (1041) // by sensor setting!! +#define LT_T_RATIO (1000000 / FPS_MAX / FMAX_720P_120_LINEAR / 8) // around ~1.0 with current setting +#define ConvertL2T(line) (line * LT_T_RATIO) // 1-Line time = 8usec = 1T, return T +#define ConvertT2L(t) ((t + (LT_T_RATIO / 2)) / LT_T_RATIO) // 1-Line time = 8usec = 1T, return Lines + +#define PAG7936_MIN_INT (ConvertT2L(10)) // ExpLine min vlaue +#define PAG7936_MAX_INT ((FMAX_720P_120_LINEAR - 11)) // ExpLine max vlaue +#define PAG7936_MIN_AGAIN (1472) // AGain min value, unit is 1/1024x +#define PAG7936_MAX_AGAIN (16384) // AGain max value, unit is 1/1024x + +#if OMV_PAG7936_MIPI +#define PAG7936_WIDTH_ALIGN (8) +#else +#define PAG7936_WIDTH_ALIGN (4) +#endif + +static const uint16_t default_regs[][2] = { + { 0x010C, 0x23 }, + { 0x010D, 0x05 }, + { 0x007B, 0x8C }, + { 0x007C, 0x8C }, + { 0x007D, 0x8C }, + { 0x007E, 0x8C }, + { 0x007F, 0x8C }, + { 0x0EAF, 0x31 }, // Interface polarity (Not default) + { 0x004C, 0x1A }, + { 0x004D, 0x41 }, + { 0x004E, 0x00 }, + { 0x004F, 0x00 }, + { 0x110A, 0x00 }, + { 0x0905, 0x60 }, + { 0x0978, 0x01 }, + { 0x0979, 0x64 }, + { 0x097C, 0xE6 }, + { 0x097D, 0x00 }, + { 0x097E, 0x08 }, + { 0x097F, 0x02 }, + { 0x0985, 0x10 }, + { 0x098B, 0x90 }, + { 0x098E, 0x06 }, + { 0x0810, 0x01 }, + { 0x0850, 0x00 }, + { 0x094A, 0x43 }, + { 0x09A0, 0x08 }, + { 0x0724, 0x10 }, + { 0x0110, 0x1B }, + { 0x0111, 0x03 }, + { 0x0114, 0xF4 }, + { 0x0186, 0x40 }, + { 0x0188, 0x14 }, + { 0x02A5, 0xEF }, + { 0x016B, 0x5D }, + { 0x0634, 0xE0 }, + { 0x0635, 0x01 }, + { 0x0646, 0x12 }, + { 0x0647, 0x02 }, + { 0x064E, 0x3A }, + { 0x064F, 0x02 }, + { 0x0654, 0x30 }, + { 0x0655, 0x02 }, + { 0x065A, 0x3F }, + { 0x065B, 0x02 }, + { 0x066A, 0x7B }, + { 0x066B, 0x02 }, + { 0x066E, 0xD2 }, + { 0x0683, 0x9E }, + { 0x0684, 0x02 }, + { 0x0687, 0xF5 }, + { 0x06B5, 0xA8 }, + { 0x06B6, 0x02 }, + { 0x06B9, 0xFF }, + { 0x06C3, 0xA3 }, + { 0x06C4, 0x02 }, + { 0x06C7, 0xFA }, + { 0x06D1, 0x12 }, + { 0x06D2, 0x02 }, + { 0x06D7, 0x76 }, + { 0x06D8, 0x02 }, + { 0x06DB, 0xCD }, + { 0x0A1A, 0x20 }, + { 0x0A32, 0x2A }, + { 0x0A33, 0x2A }, + { 0x0A34, 0x0D }, + { 0x0A35, 0x0D }, + { 0x0E10, 0x01 }, + { 0x0E11, 0x00 }, + { 0x0E12, 0x05 }, + { 0x0E13, 0x20 }, + { 0x0E14, 0x03 }, + { 0x0E15, 0x10 }, + { 0x0E16, 0x00 }, + { 0x0E17, 0x10 }, + { 0x0E18, 0x00 }, + { 0x00EB, 0x80 }, + { 0x000B, 0x02 }, + { 0x0030, 0x01 }, + { 0x0008, 0x83 }, + { 0x0000, 0x00 }, +}; + +static const uint16_t qvga_regs[][2] = { + { TG_MONO_SENSOR, 0x00 }, + { AVERAGE_MODE, 0x02 }, + { ROW_AVERAGE_MODE, 0x00 }, + { COL_AVERAGE_MODE, 0x00 }, + { ISP_WOI_EN, 0x00 }, + { HSIZE_L, 0x44 }, + { HSIZE_H, 0x01 }, + { VSIZE_L, 0xCC }, + { VSIZE_H, 0x00 }, + { WOI_HSIZE_L, 0x40 }, + { WOI_HSIZE_H, 0x01 }, + { WOI_VSIZE_L, 0xC8 }, + { WOI_VSIZE_H, 0x00 }, + { WOI_HSTART_L, 0x02 }, + { WOI_HSTART_H, 0x00 }, + { WOI_VSTART_L, 0x02 }, + { WOI_VSTART_H, 0x00 }, + { SENSOR_UPDATE, 0x80 }, + { 0x0000, 0x00 }, +}; + +static const uint16_t vga_regs[][2] = { + { TG_MONO_SENSOR, 0x00 }, + { AVERAGE_MODE, 0x01 }, + { ROW_AVERAGE_MODE, 0x00 }, + { COL_AVERAGE_MODE, 0x00 }, + { ISP_WOI_EN, 0x00 }, + { HSIZE_L, 0x88 }, + { HSIZE_H, 0x02 }, + { VSIZE_L, 0x98 }, + { VSIZE_H, 0x01 }, + { WOI_HSIZE_L, 0x80 }, + { WOI_HSIZE_H, 0x02 }, + { WOI_VSIZE_L, 0x90 }, + { WOI_VSIZE_H, 0x01 }, + { WOI_HSTART_L, 0x04 }, + { WOI_HSTART_H, 0x00 }, + { WOI_VSTART_L, 0x04 }, + { WOI_VSTART_H, 0x00 }, + { SENSOR_UPDATE, 0x80 }, + { 0x0000, 0x00 }, +}; + +static const uint16_t hd_regs[][2] = { + { TG_MONO_SENSOR, 0x00 }, + { AVERAGE_MODE, 0x00 }, + { ROW_AVERAGE_MODE, 0x00 }, + { COL_AVERAGE_MODE, 0x00 }, + { ISP_WOI_EN, 0x01 }, + { ISP_WOI_HSIZE_L, 0x00 }, + { ISP_WOI_HSIZE_H, 0x05 }, + { ISP_WOI_VSIZE_L, 0x20 }, + { ISP_WOI_VSIZE_H, 0x03 }, + { ISP_WOI_HOFFSET_L, 0x10 }, + { ISP_WOI_HOFFSET_H, 0x00 }, + { ISP_WOI_VOFFSET_L, 0x10 }, + { ISP_WOI_VOFFSET_H, 0x00 }, + { HSIZE_L, 0x10 }, + { HSIZE_H, 0x05 }, + { VSIZE_L, 0x30 }, + { VSIZE_H, 0x03 }, + { WOI_HSIZE_L, 0x10 }, + { WOI_HSIZE_H, 0x05 }, + { WOI_VSIZE_L, 0x30 }, + { WOI_VSIZE_H, 0x03 }, + { WOI_HSTART_L, 0x00 }, + { WOI_HSTART_H, 0x00 }, + { WOI_VSTART_L, 0x00 }, + { WOI_VSTART_H, 0x00 }, + { SENSOR_UPDATE, 0x80 }, + { 0x0000, 0x00 }, +}; + +static int reset(sensor_t *sensor) { + int ret = 0; + // Write default registers + for (int i = 0; default_regs[i][0] && ret == 0; i++) { + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, default_regs[i][0], default_regs[i][1]); + } + return ret; +} + +static int sleep(sensor_t *sensor, int enable) { + return 0; +} + +static int read_reg(sensor_t *sensor, uint16_t reg) { + uint8_t reg_data; + if (omv_i2c_readb2(&sensor->i2c_bus, sensor->slv_addr, reg, ®_data) != 0) { + return -1; + } + return reg_data; +} + +static int write_reg(sensor_t *sensor, uint16_t reg, uint16_t reg_data) { + return omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, reg, reg_data); +} + +static int read_reg_seq(sensor_t *sensor, uint16_t addr, size_t size, uint8_t *buf) { + int ret = 0; + for (size_t i = 0; i < size; i++) { + ret |= omv_i2c_readb2(&sensor->i2c_bus, sensor->slv_addr, addr + i, &buf[i]); + } + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) { + switch (pixformat) { + case PIXFORMAT_RGB565: + case PIXFORMAT_BAYER: + case PIXFORMAT_GRAYSCALE: + return 0; + default: + return -1; + } +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) { + int ret = 0; + const uint16_t(*regs)[2]; + + switch (framesize) { + case FRAMESIZE_HD: + regs = hd_regs; + break; + case FRAMESIZE_VGA: + regs = vga_regs; + break; + case FRAMESIZE_QVGA: + regs = qvga_regs; + break; + default: + return -1; + } + + for (int i = 0; regs[i][0] && ret == 0; i++) { + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, regs[i][0], regs[i][1]); + } + + return ret; +} + +static int set_framerate(sensor_t *sensor, int framerate) { + int ret = 0; + int32_t frame_time = FT_CLK / framerate; + int32_t integ_time = IM_CLAMP((frame_time - 11), PAG7936_MIN_INT, PAG7936_MAX_INT); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, FRAME_TIME_20_16, ((frame_time >> 16) & 0x1F)); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, FRAME_TIME_15_8, ((frame_time >> 8) & 0xFF)); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, FRAME_TIME_7_0, (frame_time & 0xFF)); + + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, AE_EXPO_MANUAL_17_16, ((integ_time >> 16) & 0x03)); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, AE_EXPO_MANUAL_15_8, ((integ_time >> 8) & 0xFF)); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, AE_EXPO_MANUAL_7_0, (integ_time & 0xFF)); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, SENSOR_UPDATE, 0x80); + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) { + return 0; +} + +static int set_hmirror(sensor_t *sensor, int enable) { + uint8_t reg; + int ret = omv_i2c_readb2(&sensor->i2c_bus, sensor->slv_addr, TG_FLIP, ®); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, TG_FLIP, TG_FLIP_SET_HFLIP(reg, enable)); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, SENSOR_UPDATE, 0x80); + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) { + uint8_t reg; + int ret = omv_i2c_readb2(&sensor->i2c_bus, sensor->slv_addr, TG_FLIP, ®); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, TG_FLIP, TG_FLIP_SET_VFLIP(reg, enable)); + ret |= omv_i2c_writeb2(&sensor->i2c_bus, sensor->slv_addr, SENSOR_UPDATE, 0x80); + return ret; +} + +static int ioctl(sensor_t *sensor, int request, va_list ap) { + int ret = 0; + + (void) read_reg_seq; + + switch (request) { + case IOCTL_GET_RGB_STATS: { + uint32_t rgb_stats[4]; + uint8_t buf[] = {(RGB_STAT_B_VS >> 8), RGB_STAT_B_VS & 0xFF }; + ret |= omv_i2c_write_bytes(&sensor->i2c_bus, sensor->slv_addr, buf, 2, OMV_I2C_XFER_NO_STOP); + ret |= omv_i2c_read_bytes(&sensor->i2c_bus, sensor->slv_addr, (uint8_t *) rgb_stats, sizeof(rgb_stats), 0); + + *va_arg(ap, uint32_t *) = rgb_stats[2]; + *va_arg(ap, uint32_t *) = rgb_stats[1]; + *va_arg(ap, uint32_t *) = rgb_stats[3]; + *va_arg(ap, uint32_t *) = rgb_stats[0]; + break; + } + default: { + ret = -1; + break; + } + } + + return ret; +} + +int pag7936_init(sensor_t *sensor) { + // Initialize sensor flags. + sensor->vsync_pol = 0; + sensor->hsync_pol = 0; + sensor->pixck_pol = 1; + sensor->mono_bpp = 1; + sensor->raw_output = 1; + sensor->cfa_format = SUBFORMAT_ID_BGGR; + + // Initialize sensor ops. + sensor->reset = reset; + sensor->sleep = sleep; + sensor->ioctl = ioctl; + sensor->read_reg = read_reg; + sensor->write_reg = write_reg; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_framerate = set_framerate; + sensor->set_colorbar = set_colorbar; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + + // Override standard resolutions + resolution[FRAMESIZE_HD][0] = 1280; + resolution[FRAMESIZE_HD][1] = 800; + + resolution[FRAMESIZE_VGA][0] = 640; + resolution[FRAMESIZE_VGA][1] = 400; + + resolution[FRAMESIZE_QVGA][0] = 320; + resolution[FRAMESIZE_QVGA][1] = 200; + return 0; +} +#endif // (OMV_PAG7936_ENABLE == 1) diff --git a/src/omv/sensors/pag7936.h b/src/omv/sensors/pag7936.h new file mode 100644 index 000000000..f174c4c7d --- /dev/null +++ b/src/omv/sensors/pag7936.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023-2024 OpenMV, LLC. + * + * 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. Any redistribution, use, or modification in source or binary form + * is done solely for personal benefit and not for any commercial + * purpose or for monetary gain. For commercial licensing options, + * please contact openmv@openmv.io + * + * THIS SOFTWARE IS PROVIDED BY THE LICENSOR AND COPYRIGHT OWNER "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 LICENSOR OR COPYRIGHT + * OWNER 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. + * + * PixArt PAG7936 driver. + */ +#ifndef __PAG7936_H__ +#define __PAG7936_H__ +#define OMV_PAG7936_XCLK_FREQ (24000000) +int pag7936_init(sensor_t *sensor); +#endif // __PAG7936_H__