sc031gs.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * SC031GS driver.
  3. *
  4. * Copyright 2022-2023 Espressif Systems (Shanghai) PTE LTD
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include <stdint.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include "sccb.h"
  23. #include "xclk.h"
  24. #include "freertos/FreeRTOS.h"
  25. #include "freertos/task.h"
  26. #include "sc031gs.h"
  27. #include "sc031gs_settings.h"
  28. #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
  29. #include "esp32-hal-log.h"
  30. #else
  31. #include "esp_log.h"
  32. static const char* TAG = "sc031gs";
  33. #endif
  34. #define SC031GS_PID_LOW_REG 0x3107
  35. #define SC031GS_PID_HIGH_REG 0x3108
  36. #define SC031GS_MAX_FRAME_WIDTH (640)
  37. #define SC031GS_MAX_FRAME_HIGH (480)
  38. #define SC031GS_GAIN_CTRL_COARSE_REG 0x3e08
  39. #define SC031GS_GAIN_CTRL_FINE_REG 0x3e09
  40. #define SC031GS_PIDH_MAGIC 0x00 // High byte of sensor ID
  41. #define SC031GS_PIDL_MAGIC 0x31 // Low byte of sensor ID
  42. static int get_reg(sensor_t *sensor, int reg, int mask)
  43. {
  44. int ret = SCCB_Read16(sensor->slv_addr, reg & 0xFFFF);
  45. if(ret > 0){
  46. ret &= mask;
  47. }
  48. return ret;
  49. }
  50. static int set_reg(sensor_t *sensor, int reg, int mask, int value)
  51. {
  52. int ret = 0;
  53. ret = SCCB_Read16(sensor->slv_addr, reg & 0xFFFF);
  54. if(ret < 0){
  55. return ret;
  56. }
  57. value = (ret & ~mask) | (value & mask);
  58. ret = SCCB_Write16(sensor->slv_addr, reg & 0xFFFF, value);
  59. return ret;
  60. }
  61. static int set_reg_bits(sensor_t *sensor, uint16_t reg, uint8_t offset, uint8_t length, uint8_t value)
  62. {
  63. int ret = 0;
  64. ret = SCCB_Read16(sensor->slv_addr, reg);
  65. if(ret < 0){
  66. return ret;
  67. }
  68. uint8_t mask = ((1 << length) - 1) << offset;
  69. value = (ret & ~mask) | ((value << offset) & mask);
  70. ret = SCCB_Write16(sensor->slv_addr, reg, value);
  71. return ret;
  72. }
  73. static int write_regs(uint8_t slv_addr, const struct sc031gs_regval *regs)
  74. {
  75. int i = 0, ret = 0;
  76. while (!ret && regs[i].addr != REG_NULL) {
  77. if (regs[i].addr == REG_DELAY) {
  78. vTaskDelay(regs[i].val / portTICK_PERIOD_MS);
  79. } else {
  80. ret = SCCB_Write16(slv_addr, regs[i].addr, regs[i].val);
  81. }
  82. i++;
  83. }
  84. return ret;
  85. }
  86. #define WRITE_REGS_OR_RETURN(regs) ret = write_regs(slv_addr, regs); if(ret){return ret;}
  87. #define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;}
  88. #define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;}
  89. static int set_hmirror(sensor_t *sensor, int enable)
  90. {
  91. int ret = 0;
  92. if(enable) {
  93. SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // mirror on
  94. } else {
  95. SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // mirror off
  96. }
  97. return ret;
  98. }
  99. static int set_vflip(sensor_t *sensor, int enable)
  100. {
  101. int ret = 0;
  102. if(enable) {
  103. SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on
  104. } else {
  105. SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off
  106. }
  107. return ret;
  108. }
  109. static int set_colorbar(sensor_t *sensor, int enable)
  110. {
  111. int ret = 0;
  112. SET_REG_BITS_OR_RETURN(0x4501, 3, 1, enable & 0x01); // enable test pattern mode
  113. SET_REG_BITS_OR_RETURN(0x3902, 6, 1, 1); // enable auto BLC, disable auto BLC if set to 0
  114. SET_REG_BITS_OR_RETURN(0x3e06, 0, 2, 3); // digital gain: 00->1x, 01->2x, 03->4x.
  115. return ret;
  116. }
  117. static int set_special_effect(sensor_t *sensor, int sleep_mode_enable) // For sc03ags sensor, This API used for sensor sleep mode control.
  118. {
  119. // Add some others special control in this API, use switch to control different funcs, such as ctrl_id.
  120. int ret = 0;
  121. SET_REG_BITS_OR_RETURN(0x0100, 0, 1, !(sleep_mode_enable & 0x01)); // 0: enable sleep mode. In sleep mode, the registers can be accessed.
  122. return ret;
  123. }
  124. int set_bpc(sensor_t *sensor, int enable) // // For sc03ags sensor, This API used to control BLC
  125. {
  126. int ret = 0;
  127. SET_REG_BITS_OR_RETURN(0x3900, 0, 1, enable & 0x01);
  128. SET_REG_BITS_OR_RETURN(0x3902, 6, 1, enable & 0x01);
  129. return ret;
  130. }
  131. static int set_agc_gain(sensor_t *sensor, int gain)
  132. {
  133. // sc031gs doesn't support AGC, use this func to control.
  134. int ret = 0;
  135. uint32_t coarse_gain, fine_gain, fine_again_reg_v, coarse_gain_reg_v;
  136. if (gain < 0x20) {
  137. WRITE_REG_OR_RETURN(0x3314, 0x3a);
  138. WRITE_REG_OR_RETURN(0x3317, 0x20);
  139. } else {
  140. WRITE_REG_OR_RETURN(0x3314, 0x44);
  141. WRITE_REG_OR_RETURN(0x3317, 0x0f);
  142. }
  143. if (gain < 0x20) { /*1x ~ 2x*/
  144. fine_gain = gain - 16;
  145. coarse_gain = 0x03;
  146. fine_again_reg_v = ((0x01 << 4) & 0x10) |
  147. (fine_gain & 0x0f);
  148. coarse_gain_reg_v = coarse_gain & 0x1F;
  149. } else if (gain < 0x40) { /*2x ~ 4x*/
  150. fine_gain = (gain >> 1) - 16;
  151. coarse_gain = 0x7;
  152. fine_again_reg_v = ((0x01 << 4) & 0x10) |
  153. (fine_gain & 0x0f);
  154. coarse_gain_reg_v = coarse_gain & 0x1F;
  155. } else if (gain < 0x80) { /*4x ~ 8x*/
  156. fine_gain = (gain >> 2) - 16;
  157. coarse_gain = 0xf;
  158. fine_again_reg_v = ((0x01 << 4) & 0x10) |
  159. (fine_gain & 0x0f);
  160. coarse_gain_reg_v = coarse_gain & 0x1F;
  161. } else { /*8x ~ 16x*/
  162. fine_gain = (gain >> 3) - 16;
  163. coarse_gain = 0x1f;
  164. fine_again_reg_v = ((0x01 << 4) & 0x10) |
  165. (fine_gain & 0x0f);
  166. coarse_gain_reg_v = coarse_gain & 0x1F;
  167. }
  168. WRITE_REG_OR_RETURN(SC031GS_GAIN_CTRL_COARSE_REG, coarse_gain_reg_v);
  169. WRITE_REG_OR_RETURN(SC031GS_GAIN_CTRL_FINE_REG, fine_again_reg_v);
  170. return ret;
  171. }
  172. static int set_aec_value(sensor_t *sensor, int value)
  173. {
  174. // For now, HDR is disabled, the sensor work in normal mode.
  175. int ret = 0;
  176. WRITE_REG_OR_RETURN(0x3e01, value & 0xFF); // AE target high
  177. WRITE_REG_OR_RETURN(0x3e02, (value >> 8) & 0xFF); // AE target low
  178. return ret;
  179. }
  180. static int reset(sensor_t *sensor)
  181. {
  182. int ret = write_regs(sensor->slv_addr, sc031gs_reset_regs);
  183. if (ret) {
  184. ESP_LOGE(TAG, "reset fail");
  185. }
  186. // printf("reg 0x3d04=%02x\r\n", get_reg(sensor, 0x3d04, 0xff));
  187. // set_colorbar(sensor, 1);
  188. return ret;
  189. }
  190. static int set_output_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h)
  191. {
  192. int ret = 0;
  193. //sc:H_start={0x3212[1:0],0x3213},H_length={0x3208[1:0],0x3209},
  194. WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_WIDTH_H_REG, ((w>>8) & 0x03));
  195. WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_WIDTH_L_REG, w & 0xff);
  196. //sc:V_start={0x3210[1:0],0x3211},V_length={0x320a[1:0],0x320b},
  197. WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_HIGH_H_REG, ((h>>8) & 0x03));
  198. WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_HIGH_L_REG, h & 0xff);
  199. vTaskDelay(10 / portTICK_PERIOD_MS);
  200. return ret;
  201. }
  202. static int set_framesize(sensor_t *sensor, framesize_t framesize)
  203. {
  204. uint16_t w = resolution[framesize].width;
  205. uint16_t h = resolution[framesize].height;
  206. struct sc031gs_regval const *framesize_regs = sc031gs_200x200_init_regs;
  207. if(framesize > FRAMESIZE_VGA) {
  208. goto err;
  209. } else if(framesize > FRAMESIZE_QVGA) {
  210. framesize_regs = sc031gs_640x480_50fps_init_regs;
  211. }
  212. uint16_t offset_x = (640-w) /2 + 4;
  213. uint16_t offset_y = (480-h) /2 + 4;
  214. int ret = write_regs(sensor->slv_addr, framesize_regs);
  215. if (ret) {
  216. ESP_LOGE(TAG, "reset fail");
  217. }
  218. if(set_output_window(sensor, offset_x, offset_y, w, h)) {
  219. goto err;
  220. }
  221. sensor->status.framesize = framesize;
  222. return 0;
  223. err:
  224. ESP_LOGE(TAG, "frame size err");
  225. return -1;
  226. }
  227. static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
  228. {
  229. int ret=0;
  230. sensor->pixformat = pixformat;
  231. switch (pixformat) {
  232. case PIXFORMAT_GRAYSCALE:
  233. break;
  234. default:
  235. ESP_LOGE(TAG, "Only support GRAYSCALE(Y8)");
  236. return -1;
  237. }
  238. return ret;
  239. }
  240. static int init_status(sensor_t *sensor)
  241. {
  242. return 0;
  243. }
  244. static int set_dummy(sensor_t *sensor, int val){ return -1; }
  245. static int set_xclk(sensor_t *sensor, int timer, int xclk)
  246. {
  247. int ret = 0;
  248. sensor->xclk_freq_hz = xclk * 1000000U;
  249. ret = xclk_timer_conf(timer, sensor->xclk_freq_hz);
  250. return ret;
  251. }
  252. int sc031gs_detect(int slv_addr, sensor_id_t *id)
  253. {
  254. if (SC031GS_SCCB_ADDR == slv_addr) {
  255. uint8_t MIDL = SCCB_Read16(slv_addr, SC031GS_PID_HIGH_REG);
  256. uint8_t MIDH = SCCB_Read16(slv_addr, SC031GS_PID_LOW_REG);
  257. uint16_t PID = MIDH << 8 | MIDL;
  258. if (SC031GS_PID == PID) {
  259. id->PID = PID;
  260. return PID;
  261. } else {
  262. ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
  263. }
  264. }
  265. return 0;
  266. }
  267. int sc031gs_init(sensor_t *sensor)
  268. {
  269. // Set function pointers
  270. sensor->reset = reset;
  271. sensor->init_status = init_status;
  272. sensor->set_pixformat = set_pixformat;
  273. sensor->set_framesize = set_framesize;
  274. sensor->set_colorbar = set_colorbar;
  275. sensor->set_hmirror = set_hmirror;
  276. sensor->set_vflip = set_vflip;
  277. sensor->set_agc_gain = set_agc_gain;
  278. sensor->set_aec_value = set_aec_value;
  279. sensor->set_special_effect = set_special_effect;
  280. //not supported
  281. sensor->set_awb_gain = set_dummy;
  282. sensor->set_contrast = set_dummy;
  283. sensor->set_sharpness = set_dummy;
  284. sensor->set_saturation= set_dummy;
  285. sensor->set_denoise = set_dummy;
  286. sensor->set_quality = set_dummy;
  287. sensor->set_special_effect = set_dummy;
  288. sensor->set_wb_mode = set_dummy;
  289. sensor->set_ae_level = set_dummy;
  290. sensor->get_reg = get_reg;
  291. sensor->set_reg = set_reg;
  292. sensor->set_xclk = set_xclk;
  293. ESP_LOGD(TAG, "sc031gs Attached");
  294. return 0;
  295. }