ov2640.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /*
  2. * This file is part of the OpenMV project.
  3. * Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
  4. * This work is licensed under the MIT license, see the file LICENSE for details.
  5. *
  6. * OV2640 driver.
  7. *
  8. */
  9. #include <stdint.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "sccb.h"
  13. #include "xclk.h"
  14. #include "ov2640.h"
  15. #include "ov2640_regs.h"
  16. #include "ov2640_settings.h"
  17. #include "freertos/FreeRTOS.h"
  18. #include "freertos/task.h"
  19. #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
  20. #include "esp32-hal-log.h"
  21. #else
  22. #include "esp_log.h"
  23. static const char* TAG = "ov2640";
  24. #endif
  25. static volatile ov2640_bank_t reg_bank = BANK_MAX;
  26. static int set_bank(sensor_t *sensor, ov2640_bank_t bank)
  27. {
  28. int res = 0;
  29. if (bank != reg_bank) {
  30. reg_bank = bank;
  31. res = SCCB_Write(sensor->slv_addr, BANK_SEL, bank);
  32. }
  33. return res;
  34. }
  35. static int write_regs(sensor_t *sensor, const uint8_t (*regs)[2])
  36. {
  37. int i=0, res = 0;
  38. while (regs[i][0]) {
  39. if (regs[i][0] == BANK_SEL) {
  40. res = set_bank(sensor, regs[i][1]);
  41. } else {
  42. res = SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]);
  43. }
  44. if (res) {
  45. return res;
  46. }
  47. i++;
  48. }
  49. return res;
  50. }
  51. static int write_reg(sensor_t *sensor, ov2640_bank_t bank, uint8_t reg, uint8_t value)
  52. {
  53. int ret = set_bank(sensor, bank);
  54. if(!ret) {
  55. ret = SCCB_Write(sensor->slv_addr, reg, value);
  56. }
  57. return ret;
  58. }
  59. static int set_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t offset, uint8_t mask, uint8_t value)
  60. {
  61. int ret = 0;
  62. uint8_t c_value, new_value;
  63. ret = set_bank(sensor, bank);
  64. if(ret) {
  65. return ret;
  66. }
  67. c_value = SCCB_Read(sensor->slv_addr, reg);
  68. new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset);
  69. ret = SCCB_Write(sensor->slv_addr, reg, new_value);
  70. return ret;
  71. }
  72. static int read_reg(sensor_t *sensor, ov2640_bank_t bank, uint8_t reg)
  73. {
  74. if(set_bank(sensor, bank)){
  75. return 0;
  76. }
  77. return SCCB_Read(sensor->slv_addr, reg);
  78. }
  79. static uint8_t get_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t offset, uint8_t mask)
  80. {
  81. return (read_reg(sensor, bank, reg) >> offset) & mask;
  82. }
  83. static int write_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t mask, int enable)
  84. {
  85. return set_reg_bits(sensor, bank, reg, 0, mask, enable?mask:0);
  86. }
  87. #define WRITE_REGS_OR_RETURN(regs) ret = write_regs(sensor, regs); if(ret){return ret;}
  88. #define WRITE_REG_OR_RETURN(bank, reg, val) ret = write_reg(sensor, bank, reg, val); if(ret){return ret;}
  89. #define SET_REG_BITS_OR_RETURN(bank, reg, offset, mask, val) ret = set_reg_bits(sensor, bank, reg, offset, mask, val); if(ret){return ret;}
  90. static int reset(sensor_t *sensor)
  91. {
  92. int ret = 0;
  93. WRITE_REG_OR_RETURN(BANK_SENSOR, COM7, COM7_SRST);
  94. vTaskDelay(10 / portTICK_PERIOD_MS);
  95. WRITE_REGS_OR_RETURN(ov2640_settings_cif);
  96. return ret;
  97. }
  98. static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
  99. {
  100. int ret = 0;
  101. sensor->pixformat = pixformat;
  102. switch (pixformat) {
  103. case PIXFORMAT_RGB565:
  104. case PIXFORMAT_RGB888:
  105. WRITE_REGS_OR_RETURN(ov2640_settings_rgb565);
  106. break;
  107. case PIXFORMAT_YUV422:
  108. case PIXFORMAT_GRAYSCALE:
  109. WRITE_REGS_OR_RETURN(ov2640_settings_yuv422);
  110. break;
  111. case PIXFORMAT_JPEG:
  112. WRITE_REGS_OR_RETURN(ov2640_settings_jpeg3);
  113. break;
  114. default:
  115. ret = -1;
  116. break;
  117. }
  118. if(!ret) {
  119. vTaskDelay(10 / portTICK_PERIOD_MS);
  120. }
  121. return ret;
  122. }
  123. static int set_window(sensor_t *sensor, ov2640_sensor_mode_t mode, int offset_x, int offset_y, int max_x, int max_y, int w, int h){
  124. int ret = 0;
  125. const uint8_t (*regs)[2];
  126. ov2640_clk_t c;
  127. c.reserved = 0;
  128. max_x /= 4;
  129. max_y /= 4;
  130. w /= 4;
  131. h /= 4;
  132. uint8_t win_regs[][2] = {
  133. {BANK_SEL, BANK_DSP},
  134. {HSIZE, max_x & 0xFF},
  135. {VSIZE, max_y & 0xFF},
  136. {XOFFL, offset_x & 0xFF},
  137. {YOFFL, offset_y & 0xFF},
  138. {VHYX, ((max_y >> 1) & 0X80) | ((offset_y >> 4) & 0X70) | ((max_x >> 5) & 0X08) | ((offset_x >> 8) & 0X07)},
  139. {TEST, (max_x >> 2) & 0X80},
  140. {ZMOW, (w)&0xFF},
  141. {ZMOH, (h)&0xFF},
  142. {ZMHH, ((h>>6)&0x04)|((w>>8)&0x03)},
  143. {0, 0}
  144. };
  145. if (sensor->pixformat == PIXFORMAT_JPEG) {
  146. c.clk_2x = 0;
  147. c.clk_div = 0;
  148. c.pclk_auto = 0;
  149. c.pclk_div = 8;
  150. if(mode == OV2640_MODE_UXGA) {
  151. c.pclk_div = 12;
  152. }
  153. // if (sensor->xclk_freq_hz == 16000000) {
  154. // c.pclk_div = c.pclk_div / 2;
  155. // }
  156. } else {
  157. #if CONFIG_IDF_TARGET_ESP32
  158. c.clk_2x = 0;
  159. #else
  160. c.clk_2x = 1;
  161. #endif
  162. c.clk_div = 7;
  163. c.pclk_auto = 1;
  164. c.pclk_div = 8;
  165. if (mode == OV2640_MODE_CIF) {
  166. c.clk_div = 3;
  167. } else if(mode == OV2640_MODE_UXGA) {
  168. c.pclk_div = 12;
  169. }
  170. }
  171. ESP_LOGI(TAG, "Set PLL: clk_2x: %u, clk_div: %u, pclk_auto: %u, pclk_div: %u", c.clk_2x, c.clk_div, c.pclk_auto, c.pclk_div);
  172. if (mode == OV2640_MODE_CIF) {
  173. regs = ov2640_settings_to_cif;
  174. } else if (mode == OV2640_MODE_SVGA) {
  175. regs = ov2640_settings_to_svga;
  176. } else {
  177. regs = ov2640_settings_to_uxga;
  178. }
  179. WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_BYPAS);
  180. WRITE_REGS_OR_RETURN(regs);
  181. WRITE_REGS_OR_RETURN(win_regs);
  182. WRITE_REG_OR_RETURN(BANK_SENSOR, CLKRC, c.clk);
  183. WRITE_REG_OR_RETURN(BANK_DSP, R_DVP_SP, c.pclk);
  184. WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_EN);
  185. vTaskDelay(10 / portTICK_PERIOD_MS);
  186. //required when changing resolution
  187. set_pixformat(sensor, sensor->pixformat);
  188. return ret;
  189. }
  190. static int set_framesize(sensor_t *sensor, framesize_t framesize)
  191. {
  192. int ret = 0;
  193. uint16_t w = resolution[framesize].width;
  194. uint16_t h = resolution[framesize].height;
  195. aspect_ratio_t ratio = resolution[framesize].aspect_ratio;
  196. uint16_t max_x = ratio_table[ratio].max_x;
  197. uint16_t max_y = ratio_table[ratio].max_y;
  198. uint16_t offset_x = ratio_table[ratio].offset_x;
  199. uint16_t offset_y = ratio_table[ratio].offset_y;
  200. ov2640_sensor_mode_t mode = OV2640_MODE_UXGA;
  201. sensor->status.framesize = framesize;
  202. if (framesize <= FRAMESIZE_CIF) {
  203. mode = OV2640_MODE_CIF;
  204. max_x /= 4;
  205. max_y /= 4;
  206. offset_x /= 4;
  207. offset_y /= 4;
  208. if(max_y > 296){
  209. max_y = 296;
  210. }
  211. } else if (framesize <= FRAMESIZE_SVGA) {
  212. mode = OV2640_MODE_SVGA;
  213. max_x /= 2;
  214. max_y /= 2;
  215. offset_x /= 2;
  216. offset_y /= 2;
  217. }
  218. ret = set_window(sensor, mode, offset_x, offset_y, max_x, max_y, w, h);
  219. return ret;
  220. }
  221. static int set_contrast(sensor_t *sensor, int level)
  222. {
  223. int ret=0;
  224. level += 3;
  225. if (level <= 0 || level > NUM_CONTRAST_LEVELS) {
  226. return -1;
  227. }
  228. sensor->status.contrast = level-3;
  229. for (int i=0; i<7; i++) {
  230. WRITE_REG_OR_RETURN(BANK_DSP, contrast_regs[0][i], contrast_regs[level][i]);
  231. }
  232. return ret;
  233. }
  234. static int set_brightness(sensor_t *sensor, int level)
  235. {
  236. int ret=0;
  237. level += 3;
  238. if (level <= 0 || level > NUM_BRIGHTNESS_LEVELS) {
  239. return -1;
  240. }
  241. sensor->status.brightness = level-3;
  242. for (int i=0; i<5; i++) {
  243. WRITE_REG_OR_RETURN(BANK_DSP, brightness_regs[0][i], brightness_regs[level][i]);
  244. }
  245. return ret;
  246. }
  247. static int set_saturation(sensor_t *sensor, int level)
  248. {
  249. int ret=0;
  250. level += 3;
  251. if (level <= 0 || level > NUM_SATURATION_LEVELS) {
  252. return -1;
  253. }
  254. sensor->status.saturation = level-3;
  255. for (int i=0; i<5; i++) {
  256. WRITE_REG_OR_RETURN(BANK_DSP, saturation_regs[0][i], saturation_regs[level][i]);
  257. }
  258. return ret;
  259. }
  260. static int set_special_effect(sensor_t *sensor, int effect)
  261. {
  262. int ret=0;
  263. effect++;
  264. if (effect <= 0 || effect > NUM_SPECIAL_EFFECTS) {
  265. return -1;
  266. }
  267. sensor->status.special_effect = effect-1;
  268. for (int i=0; i<5; i++) {
  269. WRITE_REG_OR_RETURN(BANK_DSP, special_effects_regs[0][i], special_effects_regs[effect][i]);
  270. }
  271. return ret;
  272. }
  273. static int set_wb_mode(sensor_t *sensor, int mode)
  274. {
  275. int ret=0;
  276. if (mode < 0 || mode > NUM_WB_MODES) {
  277. return -1;
  278. }
  279. sensor->status.wb_mode = mode;
  280. SET_REG_BITS_OR_RETURN(BANK_DSP, 0XC7, 6, 1, mode?1:0);
  281. if(mode) {
  282. for (int i=0; i<3; i++) {
  283. WRITE_REG_OR_RETURN(BANK_DSP, wb_modes_regs[0][i], wb_modes_regs[mode][i]);
  284. }
  285. }
  286. return ret;
  287. }
  288. static int set_ae_level(sensor_t *sensor, int level)
  289. {
  290. int ret=0;
  291. level += 3;
  292. if (level <= 0 || level > NUM_AE_LEVELS) {
  293. return -1;
  294. }
  295. sensor->status.ae_level = level-3;
  296. for (int i=0; i<3; i++) {
  297. WRITE_REG_OR_RETURN(BANK_SENSOR, ae_levels_regs[0][i], ae_levels_regs[level][i]);
  298. }
  299. return ret;
  300. }
  301. static int set_quality(sensor_t *sensor, int quality)
  302. {
  303. if(quality < 0) {
  304. quality = 0;
  305. } else if(quality > 63) {
  306. quality = 63;
  307. }
  308. sensor->status.quality = quality;
  309. return write_reg(sensor, BANK_DSP, QS, quality);
  310. }
  311. static int set_agc_gain(sensor_t *sensor, int gain)
  312. {
  313. if(gain < 0) {
  314. gain = 0;
  315. } else if(gain > 30) {
  316. gain = 30;
  317. }
  318. sensor->status.agc_gain = gain;
  319. return write_reg(sensor, BANK_SENSOR, GAIN, agc_gain_tbl[gain]);
  320. }
  321. static int set_gainceiling_sensor(sensor_t *sensor, gainceiling_t gainceiling)
  322. {
  323. sensor->status.gainceiling = gainceiling;
  324. //return write_reg(sensor, BANK_SENSOR, COM9, COM9_AGC_SET(gainceiling));
  325. return set_reg_bits(sensor, BANK_SENSOR, COM9, 5, 7, gainceiling);
  326. }
  327. static int set_aec_value(sensor_t *sensor, int value)
  328. {
  329. if(value < 0) {
  330. value = 0;
  331. } else if(value > 1200) {
  332. value = 1200;
  333. }
  334. sensor->status.aec_value = value;
  335. return set_reg_bits(sensor, BANK_SENSOR, REG04, 0, 3, value & 0x3)
  336. || write_reg(sensor, BANK_SENSOR, AEC, (value >> 2) & 0xFF)
  337. || set_reg_bits(sensor, BANK_SENSOR, REG45, 0, 0x3F, value >> 10);
  338. }
  339. static int set_aec2(sensor_t *sensor, int enable)
  340. {
  341. sensor->status.aec2 = enable;
  342. return set_reg_bits(sensor, BANK_DSP, CTRL0, 6, 1, enable?0:1);
  343. }
  344. static int set_colorbar(sensor_t *sensor, int enable)
  345. {
  346. sensor->status.colorbar = enable;
  347. return write_reg_bits(sensor, BANK_SENSOR, COM7, COM7_COLOR_BAR, enable?1:0);
  348. }
  349. static int set_agc_sensor(sensor_t *sensor, int enable)
  350. {
  351. sensor->status.agc = enable;
  352. return write_reg_bits(sensor, BANK_SENSOR, COM8, COM8_AGC_EN, enable?1:0);
  353. }
  354. static int set_aec_sensor(sensor_t *sensor, int enable)
  355. {
  356. sensor->status.aec = enable;
  357. return write_reg_bits(sensor, BANK_SENSOR, COM8, COM8_AEC_EN, enable?1:0);
  358. }
  359. static int set_hmirror_sensor(sensor_t *sensor, int enable)
  360. {
  361. sensor->status.hmirror = enable;
  362. return write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_HFLIP_IMG, enable?1:0);
  363. }
  364. static int set_vflip_sensor(sensor_t *sensor, int enable)
  365. {
  366. int ret = 0;
  367. sensor->status.vflip = enable;
  368. ret = write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_VREF_EN, enable?1:0);
  369. return ret & write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_VFLIP_IMG, enable?1:0);
  370. }
  371. static int set_raw_gma_dsp(sensor_t *sensor, int enable)
  372. {
  373. sensor->status.raw_gma = enable;
  374. return set_reg_bits(sensor, BANK_DSP, CTRL1, 5, 1, enable?1:0);
  375. }
  376. static int set_awb_dsp(sensor_t *sensor, int enable)
  377. {
  378. sensor->status.awb = enable;
  379. return set_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1, enable?1:0);
  380. }
  381. static int set_awb_gain_dsp(sensor_t *sensor, int enable)
  382. {
  383. sensor->status.awb_gain = enable;
  384. return set_reg_bits(sensor, BANK_DSP, CTRL1, 2, 1, enable?1:0);
  385. }
  386. static int set_lenc_dsp(sensor_t *sensor, int enable)
  387. {
  388. sensor->status.lenc = enable;
  389. return set_reg_bits(sensor, BANK_DSP, CTRL1, 1, 1, enable?1:0);
  390. }
  391. static int set_dcw_dsp(sensor_t *sensor, int enable)
  392. {
  393. sensor->status.dcw = enable;
  394. return set_reg_bits(sensor, BANK_DSP, CTRL2, 5, 1, enable?1:0);
  395. }
  396. static int set_bpc_dsp(sensor_t *sensor, int enable)
  397. {
  398. sensor->status.bpc = enable;
  399. return set_reg_bits(sensor, BANK_DSP, CTRL3, 7, 1, enable?1:0);
  400. }
  401. static int set_wpc_dsp(sensor_t *sensor, int enable)
  402. {
  403. sensor->status.wpc = enable;
  404. return set_reg_bits(sensor, BANK_DSP, CTRL3, 6, 1, enable?1:0);
  405. }
  406. //unsupported
  407. static int set_sharpness(sensor_t *sensor, int level)
  408. {
  409. return -1;
  410. }
  411. static int set_denoise(sensor_t *sensor, int level)
  412. {
  413. return -1;
  414. }
  415. static int get_reg(sensor_t *sensor, int reg, int mask)
  416. {
  417. int ret = read_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF);
  418. if(ret > 0){
  419. ret &= mask;
  420. }
  421. return ret;
  422. }
  423. static int set_reg(sensor_t *sensor, int reg, int mask, int value)
  424. {
  425. int ret = 0;
  426. ret = read_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF);
  427. if(ret < 0){
  428. return ret;
  429. }
  430. value = (ret & ~mask) | (value & mask);
  431. ret = write_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF, value);
  432. return ret;
  433. }
  434. 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)
  435. {
  436. return set_window(sensor, (ov2640_sensor_mode_t)startX, offsetX, offsetY, totalX, totalY, outputX, outputY);
  437. }
  438. 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)
  439. {
  440. return -1;
  441. }
  442. static int set_xclk(sensor_t *sensor, int timer, int xclk)
  443. {
  444. int ret = 0;
  445. sensor->xclk_freq_hz = xclk * 1000000U;
  446. ret = xclk_timer_conf(timer, sensor->xclk_freq_hz);
  447. return ret;
  448. }
  449. static int init_status(sensor_t *sensor){
  450. sensor->status.brightness = 0;
  451. sensor->status.contrast = 0;
  452. sensor->status.saturation = 0;
  453. sensor->status.ae_level = 0;
  454. sensor->status.special_effect = 0;
  455. sensor->status.wb_mode = 0;
  456. sensor->status.agc_gain = 30;
  457. int agc_gain = read_reg(sensor, BANK_SENSOR, GAIN);
  458. for (int i=0; i<30; i++){
  459. if(agc_gain >= agc_gain_tbl[i] && agc_gain < agc_gain_tbl[i+1]){
  460. sensor->status.agc_gain = i;
  461. break;
  462. }
  463. }
  464. sensor->status.aec_value = ((uint16_t)get_reg_bits(sensor, BANK_SENSOR, REG45, 0, 0x3F) << 10)
  465. | ((uint16_t)read_reg(sensor, BANK_SENSOR, AEC) << 2)
  466. | get_reg_bits(sensor, BANK_SENSOR, REG04, 0, 3);//0 - 1200
  467. sensor->status.quality = read_reg(sensor, BANK_DSP, QS);
  468. sensor->status.gainceiling = get_reg_bits(sensor, BANK_SENSOR, COM9, 5, 7);
  469. sensor->status.awb = get_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1);
  470. sensor->status.awb_gain = get_reg_bits(sensor, BANK_DSP, CTRL1, 2, 1);
  471. sensor->status.aec = get_reg_bits(sensor, BANK_SENSOR, COM8, 0, 1);
  472. sensor->status.aec2 = get_reg_bits(sensor, BANK_DSP, CTRL0, 6, 1);
  473. sensor->status.agc = get_reg_bits(sensor, BANK_SENSOR, COM8, 2, 1);
  474. sensor->status.bpc = get_reg_bits(sensor, BANK_DSP, CTRL3, 7, 1);
  475. sensor->status.wpc = get_reg_bits(sensor, BANK_DSP, CTRL3, 6, 1);
  476. sensor->status.raw_gma = get_reg_bits(sensor, BANK_DSP, CTRL1, 5, 1);
  477. sensor->status.lenc = get_reg_bits(sensor, BANK_DSP, CTRL1, 1, 1);
  478. sensor->status.hmirror = get_reg_bits(sensor, BANK_SENSOR, REG04, 7, 1);
  479. sensor->status.vflip = get_reg_bits(sensor, BANK_SENSOR, REG04, 6, 1);
  480. sensor->status.dcw = get_reg_bits(sensor, BANK_DSP, CTRL2, 5, 1);
  481. sensor->status.colorbar = get_reg_bits(sensor, BANK_SENSOR, COM7, 1, 1);
  482. sensor->status.sharpness = 0;//not supported
  483. sensor->status.denoise = 0;
  484. return 0;
  485. }
  486. int ov2640_detect(int slv_addr, sensor_id_t *id)
  487. {
  488. if (OV2640_SCCB_ADDR == slv_addr) {
  489. SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor
  490. uint16_t PID = SCCB_Read(slv_addr, 0x0A);
  491. if (OV2640_PID == PID) {
  492. id->PID = PID;
  493. id->VER = SCCB_Read(slv_addr, REG_VER);
  494. id->MIDL = SCCB_Read(slv_addr, REG_MIDL);
  495. id->MIDH = SCCB_Read(slv_addr, REG_MIDH);
  496. return PID;
  497. } else {
  498. ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
  499. }
  500. }
  501. return 0;
  502. }
  503. int ov2640_init(sensor_t *sensor)
  504. {
  505. sensor->reset = reset;
  506. sensor->init_status = init_status;
  507. sensor->set_pixformat = set_pixformat;
  508. sensor->set_framesize = set_framesize;
  509. sensor->set_contrast = set_contrast;
  510. sensor->set_brightness= set_brightness;
  511. sensor->set_saturation= set_saturation;
  512. sensor->set_quality = set_quality;
  513. sensor->set_colorbar = set_colorbar;
  514. sensor->set_gainceiling = set_gainceiling_sensor;
  515. sensor->set_gain_ctrl = set_agc_sensor;
  516. sensor->set_exposure_ctrl = set_aec_sensor;
  517. sensor->set_hmirror = set_hmirror_sensor;
  518. sensor->set_vflip = set_vflip_sensor;
  519. sensor->set_whitebal = set_awb_dsp;
  520. sensor->set_aec2 = set_aec2;
  521. sensor->set_aec_value = set_aec_value;
  522. sensor->set_special_effect = set_special_effect;
  523. sensor->set_wb_mode = set_wb_mode;
  524. sensor->set_ae_level = set_ae_level;
  525. sensor->set_dcw = set_dcw_dsp;
  526. sensor->set_bpc = set_bpc_dsp;
  527. sensor->set_wpc = set_wpc_dsp;
  528. sensor->set_awb_gain = set_awb_gain_dsp;
  529. sensor->set_agc_gain = set_agc_gain;
  530. sensor->set_raw_gma = set_raw_gma_dsp;
  531. sensor->set_lenc = set_lenc_dsp;
  532. //not supported
  533. sensor->set_sharpness = set_sharpness;
  534. sensor->set_denoise = set_denoise;
  535. sensor->get_reg = get_reg;
  536. sensor->set_reg = set_reg;
  537. sensor->set_res_raw = set_res_raw;
  538. sensor->set_pll = _set_pll;
  539. sensor->set_xclk = set_xclk;
  540. ESP_LOGD(TAG, "OV2640 Attached");
  541. return 0;
  542. }