ll_cam.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. // Copyright 2010-2020 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. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include "soc/system_reg.h"
  17. #include "soc/i2s_struct.h"
  18. #include "hal/gpio_ll.h"
  19. #include "ll_cam.h"
  20. #include "xclk.h"
  21. #include "cam_hal.h"
  22. #if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3)
  23. #include "esp_rom_gpio.h"
  24. #endif
  25. #if (ESP_IDF_VERSION_MAJOR >= 5)
  26. #define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE
  27. #define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE
  28. #define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
  29. #define ets_delay_us(a) esp_rom_delay_us(a)
  30. #endif
  31. static const char *TAG = "s2 ll_cam";
  32. #define I2S_ISR_ENABLE(i) {I2S0.int_clr.i = 1;I2S0.int_ena.i = 1;}
  33. #define I2S_ISR_DISABLE(i) {I2S0.int_ena.i = 0;I2S0.int_clr.i = 1;}
  34. static void CAMERA_ISR_IRAM_ATTR ll_cam_vsync_isr(void *arg)
  35. {
  36. //DBG_PIN_SET(1);
  37. cam_obj_t *cam = (cam_obj_t *)arg;
  38. BaseType_t HPTaskAwoken = pdFALSE;
  39. // filter
  40. ets_delay_us(1);
  41. if (gpio_ll_get_level(&GPIO, cam->vsync_pin) == !cam->vsync_invert) {
  42. ll_cam_send_event(cam, CAM_VSYNC_EVENT, &HPTaskAwoken);
  43. }
  44. if (HPTaskAwoken == pdTRUE) {
  45. portYIELD_FROM_ISR();
  46. }
  47. //DBG_PIN_SET(0);
  48. }
  49. static void CAMERA_ISR_IRAM_ATTR ll_cam_dma_isr(void *arg)
  50. {
  51. cam_obj_t *cam = (cam_obj_t *)arg;
  52. BaseType_t HPTaskAwoken = pdFALSE;
  53. typeof(I2S0.int_st) status = I2S0.int_st;
  54. if (status.val == 0) {
  55. return;
  56. }
  57. I2S0.int_clr.val = status.val;
  58. if (status.in_suc_eof) {
  59. ll_cam_send_event(cam, CAM_IN_SUC_EOF_EVENT, &HPTaskAwoken);
  60. }
  61. if (HPTaskAwoken == pdTRUE) {
  62. portYIELD_FROM_ISR();
  63. }
  64. }
  65. bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
  66. {
  67. I2S0.conf.rx_start = 0;
  68. if (cam->jpeg_mode || !cam->psram_mode) {
  69. I2S_ISR_DISABLE(in_suc_eof);
  70. }
  71. I2S0.in_link.stop = 1;
  72. return true;
  73. }
  74. esp_err_t ll_cam_deinit(cam_obj_t *cam)
  75. {
  76. gpio_isr_handler_remove(cam->vsync_pin);
  77. if (cam->cam_intr_handle) {
  78. esp_intr_free(cam->cam_intr_handle);
  79. cam->cam_intr_handle = NULL;
  80. }
  81. return ESP_OK;
  82. }
  83. bool ll_cam_start(cam_obj_t *cam, int frame_pos)
  84. {
  85. I2S0.conf.rx_start = 0;
  86. if (cam->jpeg_mode || !cam->psram_mode) {
  87. I2S_ISR_ENABLE(in_suc_eof);
  88. }
  89. I2S0.conf.rx_reset = 1;
  90. I2S0.conf.rx_reset = 0;
  91. I2S0.conf.rx_fifo_reset = 1;
  92. I2S0.conf.rx_fifo_reset = 0;
  93. I2S0.lc_conf.in_rst = 1;
  94. I2S0.lc_conf.in_rst = 0;
  95. I2S0.lc_conf.ahbm_fifo_rst = 1;
  96. I2S0.lc_conf.ahbm_fifo_rst = 0;
  97. I2S0.lc_conf.ahbm_rst = 1;
  98. I2S0.lc_conf.ahbm_rst = 0;
  99. I2S0.rx_eof_num = cam->dma_half_buffer_size; // Ping pong operation
  100. if (!cam->psram_mode) {
  101. I2S0.in_link.addr = ((uint32_t)&cam->dma[0]) & 0xfffff;
  102. } else {
  103. I2S0.in_link.addr = ((uint32_t)&cam->frames[frame_pos].dma[0]) & 0xfffff;
  104. }
  105. I2S0.in_link.start = 1;
  106. I2S0.conf.rx_start = 1;
  107. return true;
  108. }
  109. esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config)
  110. {
  111. esp_err_t err = camera_enable_out_clock(config);
  112. if(err != ESP_OK) {
  113. return err;
  114. }
  115. periph_module_enable(PERIPH_I2S0_MODULE);
  116. // Configure the clock
  117. I2S0.clkm_conf.clkm_div_num = 2; // 160MHz / 2 = 80MHz
  118. I2S0.clkm_conf.clkm_div_b = 0;
  119. I2S0.clkm_conf.clkm_div_a = 0;
  120. I2S0.clkm_conf.clk_sel = 2;
  121. I2S0.clkm_conf.clk_en = 1;
  122. I2S0.conf.val = 0;
  123. I2S0.fifo_conf.val = 0;
  124. I2S0.fifo_conf.dscr_en = 1;
  125. I2S0.lc_conf.ahbm_fifo_rst = 1;
  126. I2S0.lc_conf.ahbm_fifo_rst = 0;
  127. I2S0.lc_conf.ahbm_rst = 1;
  128. I2S0.lc_conf.ahbm_rst = 0;
  129. I2S0.lc_conf.check_owner = 0;
  130. //I2S0.lc_conf.indscr_burst_en = 1;
  131. //I2S0.lc_conf.ext_mem_bk_size = 0; // DMA access external memory block size. 0: 16 bytes, 1: 32 bytes, 2:64 bytes, 3:reserved
  132. I2S0.timing.val = 0;
  133. I2S0.int_ena.val = 0;
  134. I2S0.int_clr.val = ~0;
  135. I2S0.conf2.lcd_en = 1;
  136. I2S0.conf2.camera_en = 1;
  137. // Configuration data format
  138. I2S0.conf.rx_slave_mod = 1;
  139. I2S0.conf.rx_right_first = 0;
  140. I2S0.conf.rx_msb_right = cam->swap_data;
  141. I2S0.conf.rx_short_sync = 0;
  142. I2S0.conf.rx_mono = 0;
  143. I2S0.conf.rx_msb_shift = 0;
  144. I2S0.conf.rx_dma_equal = 1;
  145. // Configure sampling rate
  146. I2S0.sample_rate_conf.rx_bck_div_num = 1;
  147. I2S0.sample_rate_conf.rx_bits_mod = 8;
  148. I2S0.conf2.i_v_sync_filter_en = 1;
  149. I2S0.conf2.i_v_sync_filter_thres = 4;
  150. I2S0.conf2.cam_sync_fifo_reset = 1;
  151. I2S0.conf2.cam_sync_fifo_reset = 0;
  152. I2S0.conf_chan.rx_chan_mod = 1;
  153. I2S0.fifo_conf.rx_fifo_mod_force_en = 1;
  154. I2S0.fifo_conf.rx_data_num = 32;
  155. I2S0.fifo_conf.rx_fifo_mod = 2;
  156. I2S0.lc_conf.in_rst = 1;
  157. I2S0.lc_conf.in_rst = 0;
  158. I2S0.conf.rx_start = 1;
  159. return ESP_OK;
  160. }
  161. void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en)
  162. {
  163. if (en) {
  164. gpio_intr_enable(cam->vsync_pin);
  165. } else {
  166. gpio_intr_disable(cam->vsync_pin);
  167. }
  168. }
  169. esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config)
  170. {
  171. gpio_config_t io_conf = {0};
  172. io_conf.intr_type = cam->vsync_invert ? GPIO_PIN_INTR_NEGEDGE : GPIO_PIN_INTR_POSEDGE;
  173. io_conf.pin_bit_mask = 1ULL << config->pin_vsync;
  174. io_conf.mode = GPIO_MODE_INPUT;
  175. io_conf.pull_up_en = 1;
  176. io_conf.pull_down_en = 0;
  177. gpio_config(&io_conf);
  178. gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | CAMERA_ISR_IRAM_FLAG);
  179. gpio_isr_handler_add(config->pin_vsync, ll_cam_vsync_isr, cam);
  180. gpio_intr_disable(config->pin_vsync);
  181. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_pclk], PIN_FUNC_GPIO);
  182. gpio_set_direction(config->pin_pclk, GPIO_MODE_INPUT);
  183. gpio_set_pull_mode(config->pin_pclk, GPIO_FLOATING);
  184. gpio_matrix_in(config->pin_pclk, I2S0I_WS_IN_IDX, false);
  185. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_vsync], PIN_FUNC_GPIO);
  186. gpio_set_direction(config->pin_vsync, GPIO_MODE_INPUT);
  187. gpio_set_pull_mode(config->pin_vsync, GPIO_FLOATING);
  188. gpio_matrix_in(config->pin_vsync, I2S0I_V_SYNC_IDX, cam->vsync_invert);
  189. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_href], PIN_FUNC_GPIO);
  190. gpio_set_direction(config->pin_href, GPIO_MODE_INPUT);
  191. gpio_set_pull_mode(config->pin_href, GPIO_FLOATING);
  192. gpio_matrix_in(config->pin_href, I2S0I_H_SYNC_IDX, false);
  193. int data_pins[8] = {
  194. config->pin_d0, config->pin_d1, config->pin_d2, config->pin_d3, config->pin_d4, config->pin_d5, config->pin_d6, config->pin_d7,
  195. };
  196. for (int i = 0; i < 8; i++) {
  197. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[data_pins[i]], PIN_FUNC_GPIO);
  198. gpio_set_direction(data_pins[i], GPIO_MODE_INPUT);
  199. gpio_set_pull_mode(data_pins[i], GPIO_FLOATING);
  200. // High bit alignment, IN16 is always the highest bit
  201. // fifo accesses data by bit, when rx_bits_mod is 8, the data needs to be aligned by 8 bits
  202. gpio_matrix_in(data_pins[i], I2S0I_DATA_IN0_IDX + 8 + i, false);
  203. }
  204. gpio_matrix_in(0x38, I2S0I_H_ENABLE_IDX, false);
  205. return ESP_OK;
  206. }
  207. esp_err_t ll_cam_init_isr(cam_obj_t *cam)
  208. {
  209. return esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LOWMED | CAMERA_ISR_IRAM_FLAG, ll_cam_dma_isr, cam, &cam->cam_intr_handle);
  210. }
  211. void ll_cam_do_vsync(cam_obj_t *cam)
  212. {
  213. ll_cam_vsync_intr_enable(cam, false);
  214. gpio_matrix_in(cam->vsync_pin, I2S0I_V_SYNC_IDX, !cam->vsync_invert);
  215. ets_delay_us(10);
  216. gpio_matrix_in(cam->vsync_pin, I2S0I_V_SYNC_IDX, cam->vsync_invert);
  217. ll_cam_vsync_intr_enable(cam, true);
  218. }
  219. uint8_t ll_cam_get_dma_align(cam_obj_t *cam)
  220. {
  221. return 64;//16 << I2S0.lc_conf.ext_mem_bk_size;
  222. }
  223. static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){
  224. size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item;
  225. size_t line_width = cam->width * cam->in_bytes_per_pixel;
  226. size_t node_size = node_max;
  227. size_t nodes_per_line = 1;
  228. size_t lines_per_node = 1;
  229. // Calculate DMA Node Size so that it's divisable by or divisor of the line width
  230. if(line_width >= node_max){
  231. // One or more nodes will be requied for one line
  232. for(size_t i = node_max; i > 0; i=i-1){
  233. if ((line_width % i) == 0) {
  234. node_size = i;
  235. nodes_per_line = line_width / node_size;
  236. break;
  237. }
  238. }
  239. } else {
  240. // One or more lines can fit into one node
  241. for(size_t i = node_max; i > 0; i=i-1){
  242. if ((i % line_width) == 0) {
  243. node_size = i;
  244. lines_per_node = node_size / line_width;
  245. while((cam->height % lines_per_node) != 0){
  246. lines_per_node = lines_per_node - 1;
  247. node_size = lines_per_node * line_width;
  248. }
  249. break;
  250. }
  251. }
  252. }
  253. ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
  254. (unsigned) (node_size * cam->dma_bytes_per_item), nodes_per_line, lines_per_node);
  255. cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item;
  256. if (cam->psram_mode) {
  257. cam->dma_buffer_size = cam->recv_size * cam->dma_bytes_per_item;
  258. cam->dma_half_buffer_cnt = 2;
  259. cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
  260. } else {
  261. size_t dma_half_buffer_max = CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX / 2 / cam->dma_bytes_per_item;
  262. if (line_width > dma_half_buffer_max) {
  263. ESP_LOGE(TAG, "Resolution too high");
  264. return 0;
  265. }
  266. // Calculate minimum EOF size = max(mode_size, line_size)
  267. size_t dma_half_buffer_min = node_size * nodes_per_line;
  268. // Calculate max EOF size divisable by node size
  269. size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min;
  270. // Adjust EOF size so that height will be divisable by the number of lines in each EOF
  271. size_t lines_per_half_buffer = dma_half_buffer / line_width;
  272. while((cam->height % lines_per_half_buffer) != 0){
  273. dma_half_buffer = dma_half_buffer - dma_half_buffer_min;
  274. lines_per_half_buffer = dma_half_buffer / line_width;
  275. }
  276. // Calculate DMA size
  277. size_t dma_buffer_max = 2 * dma_half_buffer_max;
  278. size_t dma_buffer_size = dma_buffer_max;
  279. dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
  280. ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
  281. (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item),
  282. (unsigned) lines_per_half_buffer, (unsigned) (dma_buffer_size * cam->dma_bytes_per_item));
  283. cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
  284. cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
  285. cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
  286. }
  287. return 1;
  288. }
  289. bool ll_cam_dma_sizes(cam_obj_t *cam)
  290. {
  291. cam->dma_bytes_per_item = 1;
  292. if (cam->jpeg_mode) {
  293. if (cam->psram_mode) {
  294. cam->dma_buffer_size = cam->recv_size;
  295. cam->dma_half_buffer_size = 1024;
  296. cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
  297. cam->dma_node_buffer_size = cam->dma_half_buffer_size;
  298. } else {
  299. cam->dma_half_buffer_cnt = 16;
  300. cam->dma_buffer_size = cam->dma_half_buffer_cnt * 1024;
  301. cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
  302. cam->dma_node_buffer_size = cam->dma_half_buffer_size;
  303. }
  304. } else {
  305. return ll_cam_calc_rgb_dma(cam);
  306. }
  307. return 1;
  308. }
  309. size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len)
  310. {
  311. // YUV to Grayscale
  312. if (cam->in_bytes_per_pixel == 2 && cam->fb_bytes_per_pixel == 1) {
  313. size_t end = len / 8;
  314. for (size_t i = 0; i < end; ++i) {
  315. out[0] = in[0];
  316. out[1] = in[2];
  317. out[2] = in[4];
  318. out[3] = in[6];
  319. out += 4;
  320. in += 8;
  321. }
  322. return len / 2;
  323. }
  324. // just memcpy
  325. memcpy(out, in, len);
  326. return len;
  327. }
  328. 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)
  329. {
  330. if (pix_format == PIXFORMAT_GRAYSCALE) {
  331. 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) {
  332. cam->in_bytes_per_pixel = 1; // camera sends Y8
  333. } else {
  334. cam->in_bytes_per_pixel = 2; // camera sends YU/YV
  335. }
  336. cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8
  337. } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) {
  338. cam->in_bytes_per_pixel = 2; // camera sends YU/YV
  339. cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
  340. } else if (pix_format == PIXFORMAT_JPEG) {
  341. cam->in_bytes_per_pixel = 1;
  342. cam->fb_bytes_per_pixel = 1;
  343. } else {
  344. ESP_LOGE(TAG, "Requested format is not supported");
  345. return ESP_ERR_NOT_SUPPORTED;
  346. }
  347. return ESP_OK;
  348. }