bf20a6.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. // Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <stdint.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include "freertos/FreeRTOS.h"
  18. #include "freertos/task.h"
  19. #include "sccb.h"
  20. #include "bf20a6.h"
  21. #include "bf20a6_regs.h"
  22. #include "bf20a6_settings.h"
  23. #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
  24. #include "esp32-hal-log.h"
  25. #else
  26. #include "esp_log.h"
  27. static const char *TAG = "bf20a6";
  28. #endif
  29. #define H8(v) ((v)>>8)
  30. #define L8(v) ((v)&0xff)
  31. //#define REG_DEBUG_ON
  32. static int read_reg(uint8_t slv_addr, const uint16_t reg)
  33. {
  34. int ret = SCCB_Read(slv_addr, reg);
  35. // ESP_LOGI(TAG, "READ Register 0x%02x VALUE: 0x%02x", reg, ret);
  36. #ifdef REG_DEBUG_ON
  37. if (ret < 0) {
  38. ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret);
  39. }
  40. #endif
  41. return ret;
  42. }
  43. static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value)
  44. {
  45. int ret = SCCB_Write(slv_addr, reg, value);
  46. #ifdef REG_DEBUG_ON
  47. if (ret < 0) {
  48. ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret);
  49. }
  50. #endif
  51. return ret;
  52. }
  53. #ifdef DEBUG_PRINT_REG
  54. static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask)
  55. {
  56. return (read_reg(slv_addr, reg) & mask) == mask;
  57. }
  58. static void print_regs(uint8_t slv_addr)
  59. {
  60. vTaskDelay(pdMS_TO_TICKS(100));
  61. ESP_LOGI(TAG, "REG list look ======================");
  62. for (size_t i = 0xf0; i <= 0xfe; i++) {
  63. ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
  64. }
  65. ESP_LOGI(TAG, "\npage 0 ===");
  66. write_reg(slv_addr, 0xfe, 0x00); // page 0
  67. for (size_t i = 0x03; i <= 0x24; i++) {
  68. ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
  69. }
  70. for (size_t i = 0x40; i <= 0x95; i++) {
  71. ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
  72. }
  73. ESP_LOGI(TAG, "\npage 3 ===");
  74. write_reg(slv_addr, 0xfe, 0x03); // page 3
  75. for (size_t i = 0x01; i <= 0x43; i++) {
  76. ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
  77. }
  78. }
  79. static int read_regs(uint8_t slv_addr, const uint16_t(*regs)[2])
  80. {
  81. int i = 0, ret = 0;
  82. while (regs[i][0] != REGLIST_TAIL) {
  83. if (regs[i][0] == REG_DLY) {
  84. vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
  85. } else {
  86. ret = read_reg(slv_addr, regs[i][0]);
  87. }
  88. i++;
  89. }
  90. return ret;
  91. }
  92. #endif
  93. static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value)
  94. {
  95. int ret = 0;
  96. ret = SCCB_Read(sensor->slv_addr, reg);
  97. if (ret < 0) {
  98. return ret;
  99. }
  100. uint8_t mask = ((1 << length) - 1) << offset;
  101. value = (ret & ~mask) | ((value << offset) & mask);
  102. ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value);
  103. return ret;
  104. }
  105. static int write_regs(uint8_t slv_addr, const uint16_t(*regs)[2])
  106. {
  107. int i = 0, ret = 0;
  108. while (!ret && regs[i][0] != REGLIST_TAIL) {
  109. if (regs[i][0] == REG_DLY) {
  110. vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
  111. } else {
  112. ret = write_reg(slv_addr, regs[i][0], regs[i][1]);
  113. }
  114. i++;
  115. }
  116. return ret;
  117. }
  118. static int reset(sensor_t *sensor)
  119. {
  120. int ret;
  121. // Software Reset: clear all registers and reset them to their default values
  122. ret = write_reg(sensor->slv_addr, RESET_RELATED, 0x01);
  123. if (ret) {
  124. ESP_LOGE(TAG, "Software Reset FAILED!");
  125. return ret;
  126. }
  127. vTaskDelay(100 / portTICK_PERIOD_MS);
  128. ret = write_regs(sensor->slv_addr, bf20a6_default_init_regs);
  129. if (ret == 0) {
  130. ESP_LOGD(TAG, "Camera defaults loaded");
  131. vTaskDelay(100 / portTICK_PERIOD_MS);
  132. }
  133. // int test_value = read_regs(sensor->slv_addr, bf20a6_default_init_regs);
  134. return ret;
  135. }
  136. static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
  137. {
  138. int ret = 0;
  139. switch (pixformat) {
  140. case PIXFORMAT_YUV422:
  141. set_reg_bits(sensor, 0x12, 0, 1, 0);
  142. break;
  143. case PIXFORMAT_RAW:
  144. set_reg_bits(sensor, 0x12, 0, 1, 0x1);
  145. break;
  146. default:
  147. ESP_LOGW(TAG, "set_pix unsupport format");
  148. ret = -1;
  149. break;
  150. }
  151. if (ret == 0) {
  152. sensor->pixformat = pixformat;
  153. ESP_LOGD(TAG, "Set pixformat to: %u", pixformat);
  154. }
  155. return ret;
  156. }
  157. static int set_framesize(sensor_t *sensor, framesize_t framesize)
  158. {
  159. int ret = 0;
  160. if (framesize > FRAMESIZE_VGA) {
  161. return -1;
  162. }
  163. uint16_t w = resolution[framesize].width;
  164. uint16_t h = resolution[framesize].height;
  165. sensor->status.framesize = framesize;
  166. // Write MSBs
  167. ret |= SCCB_Write(sensor->slv_addr, 0x17, 0);
  168. ret |= SCCB_Write(sensor->slv_addr, 0x18, w >> 2);
  169. ret |= SCCB_Write(sensor->slv_addr, 0x19, 0);
  170. ret |= SCCB_Write(sensor->slv_addr, 0x1a, h >> 2);
  171. // Write LSBs
  172. ret |= SCCB_Write(sensor->slv_addr, 0x1b, 0);
  173. if ((w <= 320) && (h <= 240)) {
  174. ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 4));
  175. ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 4));
  176. ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 4));
  177. ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 4));
  178. } else if ((w <= 640) && (h <= 480)) {
  179. ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 8));
  180. ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 8));
  181. ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 8));
  182. ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 8));
  183. }
  184. // Delay
  185. vTaskDelay(30 / portTICK_PERIOD_MS);
  186. return ret;
  187. }
  188. static int set_hmirror(sensor_t *sensor, int enable)
  189. {
  190. int ret = 0;
  191. sensor->status.hmirror = enable;
  192. //ret = write_reg(sensor->slv_addr, 0xfe, 0x00);
  193. ret |= set_reg_bits(sensor, 0x4a, 3, 0x01, enable);
  194. if (ret == 0) {
  195. ESP_LOGD(TAG, "Set h-mirror to: %d", enable);
  196. }
  197. return ret;
  198. }
  199. static int set_vflip(sensor_t *sensor, int enable)
  200. {
  201. int ret = 0;
  202. sensor->status.vflip = enable;
  203. //ret = write_reg(sensor->slv_addr, 0xfe, 0x00);
  204. ret |= set_reg_bits(sensor, 0x4a, 2, 0x01, enable);
  205. if (ret == 0) {
  206. ESP_LOGD(TAG, "Set v-flip to: %d", enable);
  207. }
  208. return ret;
  209. }
  210. static int set_colorbar(sensor_t *sensor, int value)
  211. {
  212. int ret = 0;
  213. ret = write_reg(sensor->slv_addr, 0xb6, value);
  214. if (ret == 0) {
  215. sensor->status.colorbar = value;
  216. ESP_LOGD(TAG, "Set colorbar to: %d", value);
  217. }
  218. return ret;
  219. }
  220. static int set_sharpness(sensor_t *sensor, int level)
  221. {
  222. int ret = 0;
  223. ret = SCCB_Write(sensor->slv_addr, 0x70, level);
  224. if (ret == 0) {
  225. ESP_LOGD(TAG, "Set sharpness to: %d", level);
  226. sensor->status.sharpness = level;
  227. }
  228. return ret;
  229. }
  230. static int get_reg(sensor_t *sensor, int reg, int mask)
  231. {
  232. int ret = 0;
  233. if (mask > 0xFF) {
  234. ESP_LOGE(TAG, "mask should not more than 0xff");
  235. } else {
  236. ret = read_reg(sensor->slv_addr, reg);
  237. }
  238. if (ret > 0) {
  239. ret &= mask;
  240. }
  241. return ret;
  242. }
  243. static int set_reg(sensor_t *sensor, int reg, int mask, int value)
  244. {
  245. int ret = 0;
  246. if (mask > 0xFF) {
  247. ESP_LOGE(TAG, "mask should not more than 0xff");
  248. } else {
  249. ret = read_reg(sensor->slv_addr, reg);
  250. }
  251. if (ret < 0) {
  252. return ret;
  253. }
  254. value = (ret & ~mask) | (value & mask);
  255. if (mask > 0xFF) {
  256. } else {
  257. ret = write_reg(sensor->slv_addr, reg, value);
  258. }
  259. return ret;
  260. }
  261. static int init_status(sensor_t *sensor)
  262. {
  263. // write_reg(sensor->slv_addr, 0xfe, 0x00);
  264. sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x6f);
  265. sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0xd6);
  266. sensor->status.saturation = 0;
  267. sensor->status.sharpness = SCCB_Read(sensor->slv_addr, 0x70);
  268. sensor->status.denoise = 0;
  269. sensor->status.ae_level = 0;
  270. sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x13);
  271. sensor->status.awb = 0;
  272. sensor->status.dcw = 0;
  273. sensor->status.agc = 0;
  274. sensor->status.aec = 0;
  275. sensor->status.hmirror = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x01);
  276. sensor->status.vflip = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x02);
  277. sensor->status.colorbar = 0;
  278. sensor->status.bpc = 0;
  279. sensor->status.wpc = 0;
  280. sensor->status.raw_gma = 0;
  281. sensor->status.lenc = 0;
  282. sensor->status.quality = 0;
  283. sensor->status.special_effect = 0;
  284. sensor->status.wb_mode = 0;
  285. sensor->status.awb_gain = 0;
  286. sensor->status.agc_gain = 0;
  287. sensor->status.aec_value = 0;
  288. sensor->status.aec2 = 0;
  289. return 0;
  290. }
  291. static int set_dummy(sensor_t *sensor, int val)
  292. {
  293. ESP_LOGW(TAG, "dummy Unsupported");
  294. return -1;
  295. }
  296. static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val)
  297. {
  298. ESP_LOGW(TAG, "gainceiling Unsupported");
  299. return -1;
  300. }
  301. int bf20a6_detect(int slv_addr, sensor_id_t *id)
  302. {
  303. if (BF20A6_SCCB_ADDR == slv_addr) {
  304. uint8_t MIDL = SCCB_Read(slv_addr, SENSOR_ID_LOW);
  305. uint8_t MIDH = SCCB_Read(slv_addr, SENSOR_ID_HIGH);
  306. uint16_t PID = MIDH << 8 | MIDL;
  307. if (BF20A6_PID == PID) {
  308. id->PID = PID;
  309. return PID;
  310. } else {
  311. ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
  312. }
  313. }
  314. return 0;
  315. }
  316. int bf20a6_init(sensor_t *sensor)
  317. {
  318. sensor->init_status = init_status;
  319. sensor->reset = reset;
  320. sensor->set_pixformat = set_pixformat;
  321. sensor->set_framesize = set_framesize;
  322. sensor->set_contrast = set_dummy;
  323. sensor->set_brightness = set_dummy;
  324. sensor->set_saturation = set_dummy;
  325. sensor->set_sharpness = set_sharpness;
  326. sensor->set_denoise = set_dummy;
  327. sensor->set_gainceiling = set_gainceiling_dummy;
  328. sensor->set_quality = set_dummy;
  329. sensor->set_colorbar = set_colorbar;
  330. sensor->set_whitebal = set_dummy;
  331. sensor->set_gain_ctrl = set_dummy;
  332. sensor->set_exposure_ctrl = set_dummy;
  333. sensor->set_hmirror = set_hmirror; // set_hmirror;
  334. sensor->set_vflip = set_vflip; // set_vflip;
  335. sensor->set_aec2 = set_dummy;
  336. sensor->set_awb_gain = set_dummy;
  337. sensor->set_agc_gain = set_dummy;
  338. sensor->set_aec_value = set_dummy;
  339. sensor->set_special_effect = set_dummy;
  340. sensor->set_wb_mode = set_dummy;
  341. sensor->set_ae_level = set_dummy;
  342. sensor->set_dcw = set_dummy;
  343. sensor->set_bpc = set_dummy;
  344. sensor->set_wpc = set_dummy;
  345. sensor->set_raw_gma = set_dummy;
  346. sensor->set_lenc = set_dummy;
  347. sensor->get_reg = get_reg;
  348. sensor->set_reg = set_reg;
  349. sensor->set_res_raw = NULL;
  350. sensor->set_pll = NULL;
  351. sensor->set_xclk = NULL;
  352. ESP_LOGD(TAG, "BF20A6 Attached");
  353. return 0;
  354. }