diff --git a/CMakeLists.txt b/CMakeLists.txt index 493e4c5..ff771cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET ST sensors/sc031gs.c sensors/mega_ccm.c sensors/hm1055.c + sensors/hm0360.c ) list(APPEND priv_include_dirs diff --git a/Kconfig b/Kconfig index 991cbc3..11c2561 100755 --- a/Kconfig +++ b/Kconfig @@ -123,6 +123,13 @@ menu "Camera configuration" help Enable this option if you want to use the HM1055. Disable this option to save memory. + + config HM0360_SUPPORT + bool "Support HM0360 VGA" + default y + help + Enable this option if you want to use the HM0360. + Disable this option to save memory. config SCCB_I2C_PORT diff --git a/driver/esp_camera.c b/driver/esp_camera.c index 8985cee..eb3585e 100644 --- a/driver/esp_camera.c +++ b/driver/esp_camera.c @@ -75,6 +75,9 @@ #if CONFIG_HM1055_SUPPORT #include "hm1055.h" #endif +#if CONFIG_HM0360_SUPPORT +#include "hm0360.h" +#endif #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" @@ -155,6 +158,9 @@ static const sensor_func_t g_sensors[] = { #if CONFIG_HM1055_SUPPORT {hm1055_detect, hm1055_init}, #endif +#if CONFIG_HM0360_SUPPORT + {hm0360_detect, hm0360_init}, +#endif }; static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out_camera_model) diff --git a/driver/include/sensor.h b/driver/include/sensor.h index 354a8c0..eb02c7a 100755 --- a/driver/include/sensor.h +++ b/driver/include/sensor.h @@ -33,6 +33,7 @@ typedef enum { SC031GS_PID = 0x0031, MEGA_CCM_PID =0x039E, HM1055_PID = 0x0955, + HM0360_PID = 0x0360 } camera_pid_t; typedef enum { @@ -52,6 +53,7 @@ typedef enum { CAMERA_SC031GS, CAMERA_MEGA_CCM, CAMERA_HM1055, + CAMERA_HM0360, CAMERA_MODEL_MAX, CAMERA_NONE, } camera_model_t; @@ -73,6 +75,7 @@ typedef enum { SC031GS_SCCB_ADDR = 0x30, MEGA_CCM_SCCB_ADDR = 0x1F, // 0x3E >> 1 HM1055_SCCB_ADDR = 0x24, + HM0360_SCCB_ADDR = 0x12, } camera_sccb_addr_t; typedef enum { @@ -85,6 +88,7 @@ typedef enum { PIXFORMAT_RAW, // RAW PIXFORMAT_RGB444, // 3BP2P/RGB444 PIXFORMAT_RGB555, // 3BP2P/RGB555 + PIXFORMAT_RAW8, // RAW 8-bit } pixformat_t; typedef enum { diff --git a/driver/sensor.c b/driver/sensor.c index 847d18b..453a15f 100644 --- a/driver/sensor.c +++ b/driver/sensor.c @@ -19,6 +19,7 @@ const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = { {CAMERA_SC031GS, "SC031GS", SC031GS_SCCB_ADDR, SC031GS_PID, FRAMESIZE_VGA, false}, {CAMERA_MEGA_CCM, "MEGA_CCM", MEGA_CCM_SCCB_ADDR, MEGA_CCM_PID, FRAMESIZE_5MP, true}, {CAMERA_HM1055, "HM1055", HM1055_SCCB_ADDR, HM1055_PID, FRAMESIZE_HD, false}, + {CAMERA_HM0360, "HM0360", HM0360_SCCB_ADDR, HM0360_PID, FRAMESIZE_VGA, false}, }; const resolution_info_t resolution[FRAMESIZE_INVALID] = { diff --git a/sensors/hm0360.c b/sensors/hm0360.c new file mode 100755 index 0000000..20ec82d --- /dev/null +++ b/sensors/hm0360.c @@ -0,0 +1,410 @@ +/* + * + * HM0360 driver. + * + */ +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "hm0360.h" +#include "hm0360_regs.h" +#include "hm0360_settings.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char *TAG = "HM0360"; +#endif + +// #define REG_DEBUG_ON + +static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div); + +static int read_reg(uint8_t slv_addr, const uint16_t reg) +{ + int ret = SCCB_Read16(slv_addr, reg); +#ifdef REG_DEBUG_ON + if (ret < 0) + { + ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) +{ + return (read_reg(slv_addr, reg) & mask) == mask; +} + +static int read_reg16(uint8_t slv_addr, const uint16_t reg) +{ + int ret = 0, ret2 = 0; + ret = read_reg(slv_addr, reg); + if (ret >= 0) + { + ret = (ret & 0xFF) << 8; + ret2 = read_reg(slv_addr, reg + 1); + if (ret2 < 0) + { + ret = ret2; + } + else + { + ret |= ret2 & 0xFF; + } + } + return ret; +} + +static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) +{ + int ret = 0; +#ifndef REG_DEBUG_ON + ret = SCCB_Write16(slv_addr, reg, value); +#else + int old_value = read_reg(slv_addr, reg); + if (old_value < 0) + { + return old_value; + } + if ((uint8_t)old_value != value) + { + ESP_LOGD(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); + ret = SCCB_Write16(slv_addr, reg, value); + } + else + { + ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); + ret = SCCB_Write16(slv_addr, reg, value); // maybe not? + } + if (ret < 0) + { + ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + int ret = 0; + uint8_t c_value, new_value; + ret = read_reg(slv_addr, reg); + if (ret < 0) + { + return ret; + } + c_value = ret; + new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); + ret = write_reg(slv_addr, reg, new_value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) +{ + int i = 0, ret = 0; + while (!ret && regs[i][0] != REGLIST_TAIL) + { + if (regs[i][0] == REG_DLY) + { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } + else + { + ret = write_reg(slv_addr, regs[i][0], regs[i][1]); + } + i++; + } + return ret; +} + +static int write_reg16(uint8_t slv_addr, const uint16_t reg, uint16_t value) +{ + if (write_reg(slv_addr, reg, value >> 8) || write_reg(slv_addr, reg + 1, value)) + { + return -1; + } + return 0; +} + +static int write_addr_reg(uint8_t slv_addr, const uint16_t reg, uint16_t x_value, uint16_t y_value) +{ + if (write_reg16(slv_addr, reg, x_value) || write_reg16(slv_addr, reg + 2, y_value)) + { + return -1; + } + return 0; +} + +#define write_reg_bits(slv_addr, reg, mask, enable) set_reg_bits(slv_addr, reg, 0, mask, (enable) ? (mask) : 0) + +static int set_ae_level(sensor_t *sensor, int level); + +static int reset(sensor_t *sensor) +{ + vTaskDelay(100 / portTICK_PERIOD_MS); + int ret = 0; + // Software Reset: clear all registers and reset them to their default values + ret = write_reg(sensor->slv_addr, SW_RESET, 0x00); + if (ret) + { + ESP_LOGE(TAG, "Software Reset FAILED!"); + return ret; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + ret = write_regs(sensor->slv_addr, sensor_default_regs); + if (ret == 0) + { + ESP_LOGD(TAG, "Camera defaults loaded"); + vTaskDelay(100 / portTICK_PERIOD_MS); + set_ae_level(sensor, 0); + } + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret = 0; + + return ret; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + return ret; +} + +static int set_quality(sensor_t *sensor, int qs) +{ + return 0; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + return 0; +} + +static int set_gain_ctrl(sensor_t *sensor, int enable) +{ + return 0; +} + +static int set_exposure_ctrl(sensor_t *sensor, int enable) +{ + int ret = 0; + + return ret; +} + +// real gain +static int set_agc_gain(sensor_t *sensor, int gain) +{ + int ret = 0; + return ret; +} +static int set_aec_value(sensor_t *sensor, int value) +{ + int ret = 0; + return ret; +} + +static int set_ae_level(sensor_t *sensor, int level) +{ + int ret = 0; + return ret; +} + +static int set_brightness(sensor_t *sensor, int level) +{ + int ret = 0; + return ret; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0, ret2 = 0; + if (mask > 0xFF) + { + ret = read_reg16(sensor->slv_addr, reg); + if (ret >= 0 && mask > 0xFFFF) + { + ret2 = read_reg(sensor->slv_addr, reg + 2); + if (ret2 >= 0) + { + ret = (ret << 8) | ret2; + } + else + { + ret = ret2; + } + } + } + else + { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret > 0) + { + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0, ret2 = 0; + if (mask > 0xFF) + { + ret = read_reg16(sensor->slv_addr, reg); + if (ret >= 0 && mask > 0xFFFF) + { + ret2 = read_reg(sensor->slv_addr, reg + 2); + if (ret2 >= 0) + { + ret = (ret << 8) | ret2; + } + else + { + ret = ret2; + } + } + } + else + { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret < 0) + { + return ret; + } + value = (ret & ~mask) | (value & mask); + if (mask > 0xFFFF) + { + ret = write_reg16(sensor->slv_addr, reg, value >> 8); + if (ret >= 0) + { + ret = write_reg(sensor->slv_addr, reg + 2, value & 0xFF); + } + } + else if (mask > 0xFF) + { + ret = write_reg16(sensor->slv_addr, reg, value); + } + else + { + ret = write_reg(sensor->slv_addr, reg, value); + } + return ret; +} + +static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) +{ + return 0; +} +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + if (ret == 0) + { + ESP_LOGD(TAG, "Set xclk to %d", xclk); + } + return ret; +} + +static int init_status(sensor_t *sensor) +{ + sensor->status.brightness = 0; + sensor->status.contrast = 0; + sensor->status.saturation = 0; + // sensor->status.awb = check_reg_mask(sensor->slv_addr, AEWBCFG, 0x02); + sensor->status.agc = true; + // sensor->status.aec = check_reg_mask(sensor->slv_addr, AEWBCFG, 0x04); + // sensor->status.hmirror = check_reg_mask(sensor->slv_addr, RDCFG, 0x02); + // sensor->status.vflip = check_reg_mask(sensor->slv_addr, RDCFG, 0x01); + // sensor->status.lenc = check_reg_mask(sensor->slv_addr, ISPCTRL3, 0x40); + // sensor->status.awb_gain = read_reg(sensor->slv_addr, DGAIN); + // sensor->status.agc_gain = read_reg(sensor->slv_addr, AGAIN); + // sensor->status.aec_value = read_reg(sensor->slv_addr, AETARGM); + return 0; +} + +int hm0360_detect(int slv_addr, sensor_id_t *id) +{ + if (HM1055_SCCB_ADDR == slv_addr) + { + uint8_t h = SCCB_Read16(slv_addr, MODEL_ID_H); + uint8_t l = SCCB_Read16(slv_addr, MODEL_ID_L); + uint16_t PID = (h << 8) | l; + if (HM0360_PID == PID) + { + id->PID = PID; + id->VER = SCCB_Read16(slv_addr, SILICON_REV); + return PID; + } + else + { + ESP_LOGD(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int hm0360_init(sensor_t *sensor) +{ + sensor->reset = reset; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = NULL; + sensor->set_brightness = set_brightness; + sensor->set_saturation = NULL; + sensor->set_sharpness = NULL; + sensor->set_gainceiling = NULL; + sensor->set_quality = set_quality; + sensor->set_colorbar = set_colorbar; + sensor->set_gain_ctrl = set_gain_ctrl; + sensor->set_exposure_ctrl = set_exposure_ctrl; + sensor->set_whitebal = NULL; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + sensor->init_status = init_status; + sensor->set_aec2 = NULL; + sensor->set_aec_value = set_aec_value; + sensor->set_special_effect = NULL; + sensor->set_wb_mode = NULL; + sensor->set_ae_level = set_ae_level; + sensor->set_dcw = NULL; + sensor->set_bpc = NULL; + sensor->set_wpc = NULL; + sensor->set_agc_gain = set_agc_gain; + sensor->set_raw_gma = NULL; + sensor->set_lenc = NULL; + sensor->set_denoise = NULL; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = set_res_raw; + sensor->set_pll = NULL; + sensor->set_xclk = set_xclk; + return 0; +} diff --git a/sensors/private_include/hm0360.h b/sensors/private_include/hm0360.h new file mode 100755 index 0000000..822ecab --- /dev/null +++ b/sensors/private_include/hm0360.h @@ -0,0 +1,27 @@ +/* + * HM0360 driver. + */ +#ifndef __HM0360_H__ +#define __HM0360_H__ +#include "sensor.h" +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int hm0360_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int hm0360_init(sensor_t *sensor); + +#endif // __HM1055_H__ diff --git a/sensors/private_include/hm0360_regs.h b/sensors/private_include/hm0360_regs.h new file mode 100755 index 0000000..314ae6c --- /dev/null +++ b/sensors/private_include/hm0360_regs.h @@ -0,0 +1,86 @@ +/* + * HM1055 register definitions. + */ +#ifndef __REG_REGS_H__ +#define __REG_REGS_H__ + +// Sensor ID +#define MODEL_ID_H 0x0000 +#define MODEL_ID_L 0x0001 +#define SILICON_REV 0x0002 +#define FRAME_COUNT_H 0x0005 +#define FRAME_COUNT_L 0x0006 +#define PIXEL_ODERDER 0x0007 + +// Snesor mode control +#define MODEL_SELECT 0x0100 +#define IMAGE_ORIENTATION 0x0101 +#define EMBEDDED_LINE_EN 0x0102 +#define SW_RESET 0x0103 +#define COMMAND_UPDATE 0x0104 + +// Sensor exposure gain control +#define INTERGRATION_H 0x0202 +#define INTERGRATION_L 0x0203 +#define ANALOG_GAIN 0x0205 +#define DIGITAL_GAIN_H 0x020E +#define DIGITAL_GAIN_L 0x020F + +// clock control +#define PLL1CFG 0x0300 +#define PLL2CFG 0x0301 +#define PLL3CFG 0x0302 + +// frame timming control +#define FRAME_LENGTH_LINES_H 0x0340 +#define FRAME_LENGTH_LINES_L 0x0341 +#define LINE_LENGTH_PCK_H 0x0342 +#define LINE_LENGTH_PCK_L 0x0343 + +// monochrome programming +#define MONO_MODE 0x0370 +#define MONO_MODE_ISP 0x0371 +#define MONO_MONIDE_SEL 0x0372 + +// sub-sampling / binning control +#define H_SUB 0x0380 +#define V_SUB 0x0381 +#define BINNING 0x0382 + +// test pattern control +#define TEST_PATTERN_MODE 0x0601 +#define TEST_DATA_BLUE_H 0x0602 +#define TEST_DATA_BLUE_L 0x0603 +#define TEST_DATA_GB_H 0x0604 +#define TEST_DATA_GB_L 0x0605 +#define TEST_DATA_GR_H 0x0605 +#define TEST_DATA_GR_L 0x0606 +#define TEST_DATA_RED_H 0x0608 +#define TEST_DATA_RED_L 0x0609 + +// black level control +#define BLC_TGT 0x1004 +#define BLC2_TGT 0x1009 + +// monochrome programming +#define MONO_CTRL 0x100A + +// VSYNC / HSYNC / pixel shift +#define OPFM_CTRL 0x1014 + +// automatic exposure programming +#define AE_CTRL 0x2000 +#define AE_CTRL2 0x2001 +#define CNT_ORG_H_H 0x2002 +#define CNT_ORG_H_L 0x2003 +#define CNT_ORG_V_H 0x2004 +#define CNT_ORG_V_L 0x2005 +#define CNT_ST_H_H 0x2006 +#define CNT_ST_H_L 0x2007 +#define CNT_ST_V_H 0x2008 +#define CNT_ST_V_L 0x2009 +#define CTRL_PG_SKIPCNT 0x200A +#define BV_WIN_WEIGHT_EN 0x200D + + +#endif //__REG_REGS_H__ diff --git a/sensors/private_include/hm0360_settings.h b/sensors/private_include/hm0360_settings.h new file mode 100755 index 0000000..39f442a --- /dev/null +++ b/sensors/private_include/hm0360_settings.h @@ -0,0 +1,509 @@ + +#include + +#define REG_DLY 0xffff +#define REGLIST_TAIL 0xffff + +static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { + {0x0103, 0x00}, + // 0xffff,0xc0, + {0x3035, 0x01}, + {0x3126, 0x03}, + {0x3128, 0x57}, + {0x3142, 0x9F}, + {0x311C, 0x10}, + {0x3115, 0x42}, + {0x3116, 0x10}, + {0x3117, 0x0A}, + {0x310B, 0x10}, + {0x3031, 0x01}, + {0x312E, 0x00}, + {0x30D7, 0x00}, + {0x30DC, 0x00}, + {0x30E1, 0x00}, + {0x30E6, 0x00}, + {0x30EB, 0x00}, + {0x30F0, 0x00}, + {0x30F5, 0x00}, + {0x30FA, 0x00}, + {0x30FF, 0x00}, + {0x3104, 0x00}, + {0x30D8, 0xA7}, + {0x30DD, 0x27}, + {0x30E2, 0x27}, + {0x30E7, 0x27}, + {0x30EC, 0x27}, + {0x30F1, 0xA7}, + {0x30F6, 0x27}, + {0x30FB, 0x27}, + {0x3100, 0x27}, + {0x3105, 0x27}, + {0x30D9, 0x05}, + {0x30DE, 0x05}, + {0x30E3, 0x05}, + {0x30E8, 0x05}, + {0x30ED, 0x05}, + {0x30F2, 0x05}, + {0x30F7, 0x05}, + {0x30FC, 0x05}, + {0x3101, 0x05}, + {0x3106, 0x05}, + {0x30C4, 0x10}, + {0x30C5, 0x01}, + {0x30C6, 0xBF}, + {0x30CB, 0xFF}, + {0x30CC, 0xFF}, + {0x30CD, 0x7F}, + {0x30CE, 0x7F}, + {0x30D3, 0x01}, + {0x30D4, 0xFF}, + {0x311F, 0x0E}, + {0x3120, 0x0D}, + {0x3121, 0x0F}, + {0x3122, 0x00}, + {0x3147, 0x18}, + {0x314B, 0x01}, + {0x3149, 0x18}, + {0x3150, 0x50}, + {0x3152, 0x00}, + {0x3156, 0x2C}, + {0x3163, 0x1F}, + {0x3165, 0x7F}, + {0x312B, 0x41}, + {0x3113, 0xA0}, + {0x3114, 0x67}, + {0x317D, 0x02}, + {0x3160, 0x1F}, + {0x318C, 0x00}, + {0x315C, 0xE0}, + {0x311E, 0x0F}, + {0x30D5, 0x00}, + {0x30DA, 0x01}, + {0x30DF, 0x07}, + {0x30E4, 0x47}, + {0x30E9, 0x87}, + {0x30FD, 0x47}, + {0x3102, 0x87}, + {0x311D, 0x06}, + {0x3141, 0x2A}, + {0x315A, 0x0A}, + {0x30D6, 0x40}, + {0x30DB, 0x40}, + {0x30E0, 0x40}, + {0x30E5, 0x30}, + {0x30EA, 0x30}, + {0x30EF, 0x40}, + {0x30F4, 0x40}, + {0x30F9, 0x40}, + {0x30FE, 0x30}, + {0x3103, 0x30}, + {0x3164, 0x7F}, + {0x282A, 0x0F}, + {0x282E, 0x2F}, + {0x282B, 0x08}, + {0x312A, 0x11}, + {0x1000, 0x43}, + {0x1001, 0x80}, + {0x0350, 0xE0}, + {0x101D, 0xCF}, + {0x1021, 0x5D}, + {0x3500, 0x74}, + {0x3501, 0x0A}, + {0x3502, 0x77}, + {0x3503, 0x04}, + {0x3504, 0x14}, + {0x3505, 0x03}, + {0x3506, 0x00}, + {0x3507, 0x00}, + {0x3508, 0x00}, + {0x3509, 0x00}, + {0x350A, 0xFF}, + {0x350B, 0x00}, + {0x350D, 0x01}, + {0x350C, 0x00}, + {0x350F, 0x00}, + {0x3510, 0x01}, + {0x3513, 0x00}, + {0x351C, 0x00}, + {0x3514, 0x00}, + {0x3515, 0x01}, + {0x3516, 0x00}, + {0x3517, 0x02}, + {0x3518, 0x00}, + {0x3519, 0x7F}, + {0x351A, 0x00}, + {0x351B, 0x5F}, + {0x351D, 0x04}, + {0x351E, 0x10}, + {0x352A, 0x01}, + {0x352B, 0x04}, + {0x352C, 0x01}, + {0x352D, 0x38}, + {0x354B, 0x21}, + {0x354C, 0x01}, + {0x354D, 0xE0}, + {0x354E, 0xF0}, + {0x354F, 0x10}, + {0x3550, 0x10}, + {0x3551, 0x10}, + {0x3552, 0x20}, + {0x3553, 0x10}, + {0x3554, 0x01}, + {0x3555, 0x06}, + {0x3556, 0x0C}, + {0x3557, 0x12}, + {0x3558, 0x1C}, + {0x3559, 0x30}, + {0x3549, 0x04}, + {0x354A, 0x35}, + {0x355A, 0x74}, + {0x355B, 0x0A}, + {0x355C, 0x77}, + {0x355D, 0x04}, + {0x355E, 0x14}, + {0x355F, 0x03}, + {0x3560, 0x00}, + {0x3561, 0x01}, + {0x3562, 0x01}, + {0x3563, 0x00}, + {0x3564, 0xFF}, + {0x3565, 0x00}, + {0x3567, 0x01}, + {0x3566, 0x00}, + {0x3569, 0x00}, + {0x356A, 0x01}, + {0x356D, 0x00}, + {0x3576, 0x00}, + {0x356E, 0x00}, + {0x356F, 0x01}, + {0x3570, 0x00}, + {0x3571, 0x02}, + {0x3572, 0x00}, + {0x3573, 0x3F}, + {0x3574, 0x00}, + {0x3575, 0x2F}, + {0x3577, 0x04}, + {0x3578, 0x10}, + {0x3584, 0x01}, + {0x3585, 0x04}, + {0x3586, 0x01}, + {0x3587, 0x38}, + {0x3588, 0x02}, + {0x3589, 0x12}, + {0x358A, 0x04}, + {0x358B, 0x24}, + {0x358C, 0x06}, + {0x358D, 0x36}, + {0x35A5, 0x21}, + {0x35A6, 0x01}, + {0x35A7, 0xE0}, + {0x35A8, 0xF0}, + {0x35A9, 0x10}, + {0x35AA, 0x10}, + {0x35AB, 0x10}, + {0x35AC, 0x20}, + {0x35AD, 0x10}, + {0x35AE, 0x01}, + {0x35AF, 0x06}, + {0x35B0, 0x0C}, + {0x35B1, 0x12}, + {0x35B2, 0x1C}, + {0x35B3, 0x30}, + {0x35A3, 0x02}, + {0x35A4, 0x03}, + {0x3512, 0x3F}, + {0x351F, 0x04}, + {0x3520, 0x03}, + {0x3521, 0x00}, + {0x3523, 0x60}, + {0x3524, 0x08}, + {0x3525, 0x19}, + {0x3526, 0x08}, + {0x3527, 0x10}, + {0x356C, 0x3F}, + {0x3579, 0x04}, + {0x357A, 0x03}, + {0x357B, 0x00}, + {0x357D, 0x60}, + {0x357E, 0x08}, + {0x357F, 0x19}, + {0x3580, 0x08}, + {0x3581, 0x10}, + {0x2048, 0x00}, + {0x2049, 0x10}, + {0x204A, 0x40}, + {0x204E, 0x00}, + {0x204F, 0x38}, + {0x2050, 0xE0}, + {0x204B, 0x00}, + {0x204C, 0x08}, + {0x204D, 0x20}, + {0x2051, 0x00}, + {0x2052, 0x1C}, + {0x2053, 0x70}, + {0x2054, 0x00}, + {0x2055, 0x1A}, + {0x2056, 0xC0}, + {0x2057, 0x00}, + {0x2058, 0x06}, + {0x2059, 0xB0}, + {0x2080, 0x41}, + {0x2083, 0x01}, + {0x208D, 0x02}, + {0x208E, 0x08}, + {0x208F, 0x0D}, + {0x2090, 0x14}, + {0x2091, 0x1D}, + {0x2092, 0x30}, + {0x2093, 0x08}, + {0x2094, 0x0A}, + {0x2095, 0x0F}, + {0x2096, 0x14}, + {0x2097, 0x18}, + {0x2098, 0x20}, + {0x2099, 0x10}, + {0x209A, 0x00}, + {0x209B, 0x01}, + {0x209C, 0x01}, + {0x209D, 0x11}, + {0x209E, 0x06}, + {0x1030, 0x09}, + {0x1031, 0x12}, + {0x1032, 0x23}, + {0x1033, 0x31}, + {0x1034, 0x3E}, + {0x1035, 0x4B}, + {0x1036, 0x56}, + {0x1037, 0x5E}, + {0x1038, 0x65}, + {0x1039, 0x72}, + {0x103A, 0x7F}, + {0x103B, 0x8C}, + {0x103C, 0x98}, + {0x103D, 0xB2}, + {0x103E, 0xCC}, + {0x103F, 0xE6}, + {0x35B4, 0x74}, + {0x35B5, 0x0A}, + {0x35B6, 0x77}, + {0x35B7, 0x00}, + {0x35B8, 0x94}, + {0x35B9, 0x03}, + {0x35BA, 0x00}, + {0x35BB, 0x03}, + {0x35BD, 0x00}, + {0x35BE, 0xFF}, + {0x35BF, 0x00}, + {0x35C1, 0x01}, + {0x35C0, 0x01}, + {0x35C3, 0x00}, + {0x35C4, 0x00}, + {0x35C6, 0x3F}, + {0x35C7, 0x00}, + {0x35D0, 0x00}, + {0x35D3, 0x04}, + {0x35D7, 0x18}, + {0x35D8, 0x01}, + {0x35D9, 0x20}, + {0x35DA, 0x08}, + {0x35DB, 0x14}, + {0x35DC, 0x70}, + {0x35C8, 0x00}, + {0x35C9, 0x01}, + {0x35CA, 0x00}, + {0x35CB, 0x02}, + {0x35CC, 0x00}, + {0x35CD, 0x0F}, + {0x35CE, 0x00}, + {0x35CF, 0x0B}, + {0x35DE, 0x00}, + {0x35DF, 0x01}, + {0x35FD, 0x00}, + {0x35FE, 0x5E}, + {0x3024, 0x00}, + {0x3025, 0x12}, + {0x3026, 0x03}, + {0x3027, 0x81}, + {0x3028, 0x01}, + {0x3029, 0x00}, + {0x302A, 0x30}, + {0x2061, 0x00}, + {0x2062, 0x00}, + {0x2063, 0xC8}, + {0x1014, 0x00}, + {0x102F, 0x08}, + {0x309E, 0x05}, + {0x309F, 0x02}, + {0x30A0, 0x02}, + {0x30A1, 0x00}, + {0x30A2, 0x08}, + {0x30A3, 0x00}, + {0x30A4, 0x20}, + {0x30A5, 0x04}, + {0x30A6, 0x02}, + {0x30A7, 0x02}, + {0x30A8, 0x01}, + {0x30B0, 0x03}, + {0x3112, 0x04}, + {0x311A, 0x30}, + {0x2800, 0x00}, + {0x0370, 0x00}, + {0x0371, 0x00}, + {0x0372, 0x01}, + {0x100A, 0x05}, + {0x2590, 0x01}, + {0x0104, 0x01}, + {0x0100, 0x01}, + // 0xFFFF,0xC0, + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_framesize_HD[][2] = { + {0x0006, 0x00}, + {0x000D, 0x00}, + {0x000E, 0x00}, + {0x0122, 0xFB}, + {0x0125, 0xDF}, + {0x0126, 0x70}, + {0x05E4, 0x08}, + {0x05E5, 0x00}, + {0x05E6, 0x07}, + {0x05E7, 0x05}, + {0x05E8, 0x08}, + {0x05E9, 0x00}, + {0x05EA, 0xD7}, + {0x05EB, 0x02}, + {REGLIST_TAIL, 0x00}, +}; + +static const DRAM_ATTR uint16_t sensor_framesize_VGA[][2] = { + {0x0006, 0x10}, + {0x000D, 0x00}, + {0x000E, 0x00}, + {0x0122, 0xEB}, + {0x0125, 0xFF}, + {0x0126, 0x70}, + {0x05E0, 0XC1}, + {0x05E1, 0x00}, + {0x05E2, 0xC1}, + {0x05E3, 0x00}, + {0x05E4, 0x03}, + {0x05E5, 0x00}, + {0x05E6, 0x82}, + {0x05E7, 0x02}, + {0x05E8, 0x04}, + {0x05E9, 0x00}, + {0x05EA, 0xE3}, + {0x05EB, 0x01}, + {REGLIST_TAIL, 0x00}, +}; + +static const DRAM_ATTR uint16_t sensor_framesize_CIF[][2] = { + {0x0006, 0x00}, + {0x000D, 0x01}, + {0x000E, 0x11}, + {0x0122, 0xFB}, + {0x0125, 0xFF}, + {0x0126, 0x72}, + {0x05E0, 0XC0}, + {0x05E1, 0x00}, + {0x05E2, 0x8F}, + {0x05E3, 0x00}, + {0x05E4, 0x11}, + {0x05E5, 0x00}, + {0x05E6, 0xA0}, + {0x05E7, 0x01}, + {0x05E8, 0x08}, + {0x05E9, 0x00}, + {0x05EA, 0x2F}, + {0x05EB, 0x01}, + {REGLIST_TAIL, 0x00}, +}; + +static const DRAM_ATTR uint16_t sensor_framesize_QVGA[][2] = { + {0x0006, 0x00}, + {0x000D, 0x01}, + {0x000E, 0x11}, + {0x0122, 0xFB}, + {0x0125, 0xFF}, + {0x0126, 0x70}, + {0x05E0, 0XBE}, + {0x05E1, 0x00}, + {0x05E2, 0xBE}, + {0x05E3, 0x00}, + {0x05E4, 0x3A}, + {0x05E5, 0x00}, + {0x05E6, 0x79}, + {0x05E7, 0x01}, + {0x05E8, 0x04}, + {0x05E9, 0x00}, + {0x05EA, 0xF3}, + {0x05EB, 0x00}, + {REGLIST_TAIL, 0x00}, +}; + +static const DRAM_ATTR uint16_t sensor_framesize_QCIF[][2] = { + {0x0006, 0x00}, + {0x000D, 0x01}, + {0x000E, 0x11}, + {0x0122, 0xFB}, + {0x0125, 0xFF}, + {0x0126, 0x72}, + {0x05E0, 0X52}, + {0x05E1, 0x01}, + {0x05E2, 0x38}, + {0x05E3, 0x01}, + {0x05E4, 0x22}, + {0x05E5, 0x00}, + {0x05E6, 0xD1}, + {0x05E7, 0x00}, + {0x05E8, 0x04}, + {0x05E9, 0x00}, + {0x05EA, 0x93}, + {0x05EB, 0x00}, + {REGLIST_TAIL, 0x00}, +}; + +static const DRAM_ATTR uint16_t sensor_framesize_240X240[][2] = { + {0x0006, 0x00}, + {0x000D, 0x01}, + {0x000E, 0x11}, + {0x0122, 0xFB}, + {0x0125, 0xFF}, + {0x0126, 0x70}, + {0x05E0, 0XBE}, + {0x05E1, 0x00}, + {0x05E2, 0xBE}, + {0x05E3, 0x00}, + {0x05E4, 0x62}, + {0x05E5, 0x00}, + {0x05E6, 0x51}, + {0x05E7, 0x01}, + {0x05E8, 0x04}, + {0x05E9, 0x00}, + {0x05EA, 0xF3}, + {0x05EB, 0x00}, + {REGLIST_TAIL, 0x00}, +}; + +static const DRAM_ATTR uint16_t sensor_framesize_QQVGA[][2] = { + {0x0006, 0x00}, + {0x000D, 0x01}, + {0x000E, 0x11}, + {0x0122, 0xFB}, + {0x0125, 0xFF}, + {0x0126, 0x70}, + {0x05E0, 0X78}, + {0x05E1, 0x01}, + {0x05E2, 0x78}, + {0x05E3, 0x01}, + {0x05E4, 0x1E}, + {0x05E5, 0x00}, + {0x05E6, 0xBD}, + {0x05E7, 0x00}, + {0x05E8, 0x03}, + {0x05E9, 0x00}, + {0x05EA, 0x7A}, + {0x05EB, 0x00}, + {REGLIST_TAIL, 0x00}, +}; \ No newline at end of file diff --git a/target/esp32s3/ll_cam.c b/target/esp32s3/ll_cam.c index 71caf14..f5c1aa0 100644 --- a/target/esp32s3/ll_cam.c +++ b/target/esp32s3/ll_cam.c @@ -557,7 +557,7 @@ size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid) { if (pix_format == PIXFORMAT_GRAYSCALE) { - if (sensor_pid == OV3660_PID || sensor_pid == OV5640_PID || sensor_pid == NT99141_PID || sensor_pid == SC031GS_PID || sensor_pid == BF20A6_PID || sensor_pid == GC0308_PID) { + if (sensor_pid == OV3660_PID || sensor_pid == OV5640_PID || sensor_pid == NT99141_PID || sensor_pid == SC031GS_PID || sensor_pid == BF20A6_PID || sensor_pid == GC0308_PID || sensor_pid == HM0360_PID) { cam->in_bytes_per_pixel = 1; // camera sends Y8 } else { cam->in_bytes_per_pixel = 2; // camera sends YU/YV