ll_cam.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  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/lcd_cam_struct.h"
  18. #include "soc/lcd_cam_reg.h"
  19. #include "soc/gdma_struct.h"
  20. #include "soc/gdma_periph.h"
  21. #include "soc/gdma_reg.h"
  22. #include "hal/clk_gate_ll.h"
  23. #include "esp_private/gdma.h"
  24. #include "ll_cam.h"
  25. #include "cam_hal.h"
  26. #include "esp_rom_gpio.h"
  27. #if (ESP_IDF_VERSION_MAJOR >= 5)
  28. #include "soc/gpio_sig_map.h"
  29. #include "soc/gpio_periph.h"
  30. #include "soc/io_mux_reg.h"
  31. #define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
  32. #define gpio_matrix_out(a,b,c,d) esp_rom_gpio_connect_out_signal(a,b,c,d)
  33. #define ets_delay_us(a) esp_rom_delay_us(a)
  34. #endif
  35. #if !defined(SOC_GDMA_PAIRS_PER_GROUP) && defined(SOC_GDMA_PAIRS_PER_GROUP_MAX)
  36. #define SOC_GDMA_PAIRS_PER_GROUP SOC_GDMA_PAIRS_PER_GROUP_MAX
  37. #endif
  38. static const char *TAG = "s3 ll_cam";
  39. void ll_cam_dma_print_state(cam_obj_t *cam)
  40. {
  41. esp_rom_printf("dma_infifo_status[%u] :\n", cam->dma_num);
  42. esp_rom_printf(" infifo_full_l1 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_full_l1);
  43. esp_rom_printf(" infifo_empty_l1 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_empty_l1);
  44. esp_rom_printf(" infifo_full_l2 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_full_l2);
  45. esp_rom_printf(" infifo_empty_l2 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_empty_l2);
  46. esp_rom_printf(" infifo_full_l3 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_full_l3);
  47. esp_rom_printf(" infifo_empty_l3 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_empty_l3);
  48. esp_rom_printf(" infifo_cnt_l1 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_cnt_l1);
  49. esp_rom_printf(" infifo_cnt_l2 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_cnt_l2);
  50. esp_rom_printf(" infifo_cnt_l3 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_cnt_l3);
  51. esp_rom_printf(" in_remain_under_1b_l3: %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_remain_under_1b_l3);
  52. esp_rom_printf(" in_remain_under_2b_l3: %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_remain_under_2b_l3);
  53. esp_rom_printf(" in_remain_under_3b_l3: %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_remain_under_3b_l3);
  54. esp_rom_printf(" in_remain_under_4b_l3: %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_remain_under_4b_l3);
  55. esp_rom_printf(" in_buf_hungry : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_buf_hungry);
  56. esp_rom_printf("dma_state[%u] :\n", cam->dma_num);
  57. esp_rom_printf(" dscr_addr : 0x%lx\n", GDMA.channel[cam->dma_num].in.state.dscr_addr);
  58. esp_rom_printf(" in_dscr_state : %lu\n", GDMA.channel[cam->dma_num].in.state.in_dscr_state);
  59. esp_rom_printf(" in_state : %lu\n", GDMA.channel[cam->dma_num].in.state.in_state);
  60. }
  61. void ll_cam_dma_reset(cam_obj_t *cam)
  62. {
  63. GDMA.channel[cam->dma_num].in.int_clr.val = ~0;
  64. GDMA.channel[cam->dma_num].in.int_ena.val = 0;
  65. GDMA.channel[cam->dma_num].in.conf0.val = 0;
  66. GDMA.channel[cam->dma_num].in.conf0.in_rst = 1;
  67. GDMA.channel[cam->dma_num].in.conf0.in_rst = 0;
  68. //internal SRAM only
  69. if (!cam->psram_mode) {
  70. GDMA.channel[cam->dma_num].in.conf0.indscr_burst_en = 1;
  71. GDMA.channel[cam->dma_num].in.conf0.in_data_burst_en = 1;
  72. }
  73. GDMA.channel[cam->dma_num].in.conf1.in_check_owner = 0;
  74. // GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size = 2;
  75. GDMA.channel[cam->dma_num].in.peri_sel.sel = 5;
  76. //GDMA.channel[cam->dma_num].in.pri.rx_pri = 1;//rx prio 0-15
  77. //GDMA.channel[cam->dma_num].in.sram_size.in_size = 6;//This register is used to configure the size of L2 Tx FIFO for Rx channel. 0:16 bytes, 1:24 bytes, 2:32 bytes, 3: 40 bytes, 4: 48 bytes, 5:56 bytes, 6: 64 bytes, 7: 72 bytes, 8: 80 bytes.
  78. //GDMA.channel[cam->dma_num].in.wight.rx_weight = 7;//The weight of Rx channel 0-15
  79. }
  80. static void CAMERA_ISR_IRAM_ATTR ll_cam_vsync_isr(void *arg)
  81. {
  82. //DBG_PIN_SET(1);
  83. cam_obj_t *cam = (cam_obj_t *)arg;
  84. BaseType_t HPTaskAwoken = pdFALSE;
  85. typeof(LCD_CAM.lc_dma_int_st) status = LCD_CAM.lc_dma_int_st;
  86. if (status.val == 0) {
  87. return;
  88. }
  89. LCD_CAM.lc_dma_int_clr.val = status.val;
  90. if (status.cam_vsync_int_st) {
  91. ll_cam_send_event(cam, CAM_VSYNC_EVENT, &HPTaskAwoken);
  92. }
  93. if (HPTaskAwoken == pdTRUE) {
  94. portYIELD_FROM_ISR();
  95. }
  96. //DBG_PIN_SET(0);
  97. }
  98. static void CAMERA_ISR_IRAM_ATTR ll_cam_dma_isr(void *arg)
  99. {
  100. cam_obj_t *cam = (cam_obj_t *)arg;
  101. BaseType_t HPTaskAwoken = pdFALSE;
  102. typeof(GDMA.channel[cam->dma_num].in.int_st) status = GDMA.channel[cam->dma_num].in.int_st;
  103. if (status.val == 0) {
  104. return;
  105. }
  106. GDMA.channel[cam->dma_num].in.int_clr.val = status.val;
  107. if (status.in_suc_eof) {
  108. ll_cam_send_event(cam, CAM_IN_SUC_EOF_EVENT, &HPTaskAwoken);
  109. }
  110. if (HPTaskAwoken == pdTRUE) {
  111. portYIELD_FROM_ISR();
  112. }
  113. }
  114. bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
  115. {
  116. if (cam->jpeg_mode || !cam->psram_mode) {
  117. GDMA.channel[cam->dma_num].in.int_ena.in_suc_eof = 0;
  118. GDMA.channel[cam->dma_num].in.int_clr.in_suc_eof = 1;
  119. }
  120. GDMA.channel[cam->dma_num].in.link.stop = 1;
  121. return true;
  122. }
  123. bool ll_cam_start(cam_obj_t *cam, int frame_pos)
  124. {
  125. LCD_CAM.cam_ctrl1.cam_start = 0;
  126. if (cam->jpeg_mode || !cam->psram_mode) {
  127. GDMA.channel[cam->dma_num].in.int_clr.in_suc_eof = 1;
  128. GDMA.channel[cam->dma_num].in.int_ena.in_suc_eof = 1;
  129. }
  130. LCD_CAM.cam_ctrl1.cam_reset = 1;
  131. LCD_CAM.cam_ctrl1.cam_reset = 0;
  132. LCD_CAM.cam_ctrl1.cam_afifo_reset = 1;
  133. LCD_CAM.cam_ctrl1.cam_afifo_reset = 0;
  134. GDMA.channel[cam->dma_num].in.conf0.in_rst = 1;
  135. GDMA.channel[cam->dma_num].in.conf0.in_rst = 0;
  136. LCD_CAM.cam_ctrl1.cam_rec_data_bytelen = cam->dma_half_buffer_size - 1; // Ping pong operation
  137. if (!cam->psram_mode) {
  138. GDMA.channel[cam->dma_num].in.link.addr = ((uint32_t)&cam->dma[0]) & 0xfffff;
  139. } else {
  140. GDMA.channel[cam->dma_num].in.link.addr = ((uint32_t)&cam->frames[frame_pos].dma[0]) & 0xfffff;
  141. }
  142. GDMA.channel[cam->dma_num].in.link.start = 1;
  143. LCD_CAM.cam_ctrl.cam_update = 1;
  144. LCD_CAM.cam_ctrl1.cam_start = 1;
  145. return true;
  146. }
  147. esp_err_t ll_cam_deinit(cam_obj_t *cam)
  148. {
  149. if (cam->cam_intr_handle) {
  150. esp_intr_free(cam->cam_intr_handle);
  151. cam->cam_intr_handle = NULL;
  152. }
  153. if (cam->dma_intr_handle) {
  154. esp_intr_free(cam->dma_intr_handle);
  155. cam->dma_intr_handle = NULL;
  156. }
  157. gdma_disconnect(cam->dma_channel_handle);
  158. gdma_del_channel(cam->dma_channel_handle);
  159. cam->dma_channel_handle = NULL;
  160. // GDMA.channel[cam->dma_num].in.link.addr = 0x0;
  161. LCD_CAM.cam_ctrl1.cam_start = 0;
  162. LCD_CAM.cam_ctrl1.cam_reset = 1;
  163. LCD_CAM.cam_ctrl1.cam_reset = 0;
  164. return ESP_OK;
  165. }
  166. static esp_err_t ll_cam_dma_init(cam_obj_t *cam)
  167. {
  168. //alloc rx gdma channel
  169. gdma_channel_alloc_config_t rx_alloc_config = {
  170. .direction = GDMA_CHANNEL_DIRECTION_RX,
  171. };
  172. #if ((ESP_IDF_VERSION_MAJOR == 5 && ESP_IDF_VERSION_MINOR >= 4) || ESP_IDF_VERSION_MAJOR > 5)
  173. esp_err_t ret = gdma_new_ahb_channel(&rx_alloc_config, &cam->dma_channel_handle);
  174. #else
  175. esp_err_t ret = gdma_new_channel(&rx_alloc_config, &cam->dma_channel_handle);
  176. #endif
  177. if (ret != ESP_OK) {
  178. cam_deinit();
  179. ESP_LOGE(TAG, "Can't find available GDMA channel");
  180. return ESP_FAIL;
  181. }
  182. int chan_id = -1;
  183. ret = gdma_get_channel_id(cam->dma_channel_handle, &chan_id);
  184. if (ret != ESP_OK) {
  185. cam_deinit();
  186. ESP_LOGE(TAG, "Can't get GDMA channel number");
  187. return ESP_FAIL;
  188. }
  189. cam->dma_num = chan_id;
  190. ESP_LOGI(TAG, "DMA Channel=%d", cam->dma_num);
  191. // for (int x = (SOC_GDMA_PAIRS_PER_GROUP - 1); x >= 0; x--) {
  192. // if (GDMA.channel[x].in.link.addr == 0x0) {
  193. // cam->dma_num = x;
  194. // ESP_LOGI(TAG, "DMA Channel=%d", cam->dma_num);
  195. // break;
  196. // }
  197. // if (x == 0) {
  198. // cam_deinit();
  199. // ESP_LOGE(TAG, "Can't found available GDMA channel");
  200. // return ESP_FAIL;
  201. // }
  202. // }
  203. if (!periph_ll_periph_enabled(PERIPH_GDMA_MODULE)) {
  204. periph_ll_disable_clk_set_rst(PERIPH_GDMA_MODULE);
  205. periph_ll_enable_clk_clear_rst(PERIPH_GDMA_MODULE);
  206. }
  207. // if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN) == 0) {
  208. // REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN);
  209. // REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN);
  210. // REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
  211. // REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
  212. // }
  213. ll_cam_dma_reset(cam);
  214. return ESP_OK;
  215. }
  216. #if CONFIG_CAMERA_CONVERTER_ENABLED
  217. static esp_err_t ll_cam_converter_config(cam_obj_t *cam, const camera_config_t *config)
  218. {
  219. esp_err_t ret = ESP_OK;
  220. switch (config->conv_mode) {
  221. case YUV422_TO_YUV420:
  222. if (config->pixel_format != PIXFORMAT_YUV422) {
  223. ret = ESP_FAIL;
  224. } else {
  225. ESP_LOGI(TAG, "YUV422 to YUV420 mode");
  226. LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 1;
  227. LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0;
  228. LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 1;
  229. }
  230. break;
  231. case YUV422_TO_RGB565:
  232. if (config->pixel_format != PIXFORMAT_YUV422) {
  233. ret = ESP_FAIL;
  234. } else {
  235. ESP_LOGI(TAG, "YUV422 to RGB565 mode");
  236. LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3;
  237. LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0;
  238. LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 0;
  239. }
  240. break;
  241. default:
  242. break;
  243. }
  244. #if CONFIG_LCD_CAM_CONV_BT709_ENABLED
  245. LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 1;
  246. #else
  247. LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 0;
  248. #endif
  249. #if CONFIG_LCD_CAM_CONV_FULL_RANGE_ENABLED
  250. LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 1;
  251. LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 1;
  252. #else
  253. LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 0;
  254. LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 0;
  255. #endif
  256. LCD_CAM.cam_rgb_yuv.cam_conv_mode_8bits_on = 1;
  257. LCD_CAM.cam_rgb_yuv.cam_conv_bypass = 1;
  258. cam->conv_mode = config->conv_mode;
  259. return ret;
  260. }
  261. #endif
  262. esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config)
  263. {
  264. esp_err_t ret = ESP_OK;
  265. if (!periph_ll_periph_enabled(PERIPH_LCD_CAM_MODULE)) {
  266. periph_ll_disable_clk_set_rst(PERIPH_LCD_CAM_MODULE);
  267. periph_ll_enable_clk_clear_rst(PERIPH_LCD_CAM_MODULE);
  268. }
  269. // if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN) == 0) {
  270. // REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN);
  271. // REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN);
  272. // REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST);
  273. // REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST);
  274. // }
  275. LCD_CAM.cam_ctrl.val = 0;
  276. LCD_CAM.cam_ctrl.cam_clkm_div_b = 0;
  277. LCD_CAM.cam_ctrl.cam_clkm_div_a = 0;
  278. LCD_CAM.cam_ctrl.cam_clkm_div_num = 160000000 / config->xclk_freq_hz;
  279. LCD_CAM.cam_ctrl.cam_clk_sel = 3;//Select Camera module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: no clock.
  280. LCD_CAM.cam_ctrl.cam_stop_en = 0;
  281. LCD_CAM.cam_ctrl.cam_vsync_filter_thres = 4; // Filter by LCD_CAM clock
  282. LCD_CAM.cam_ctrl.cam_update = 0;
  283. LCD_CAM.cam_ctrl.cam_byte_order = cam->swap_data;
  284. LCD_CAM.cam_ctrl.cam_bit_order = 0;
  285. LCD_CAM.cam_ctrl.cam_line_int_en = 0;
  286. LCD_CAM.cam_ctrl.cam_vs_eof_en = 0; //1: CAM_VSYNC to generate in_suc_eof. 0: in_suc_eof is controlled by reg_cam_rec_data_cyclelen
  287. LCD_CAM.cam_ctrl1.val = 0;
  288. LCD_CAM.cam_ctrl1.cam_rec_data_bytelen = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - 1; // Cannot be assigned to 0, and it is easy to overflow
  289. LCD_CAM.cam_ctrl1.cam_line_int_num = 0; // The number of hsyncs that generate hs interrupts
  290. LCD_CAM.cam_ctrl1.cam_clk_inv = 0;
  291. LCD_CAM.cam_ctrl1.cam_vsync_filter_en = 1;
  292. LCD_CAM.cam_ctrl1.cam_2byte_en = 0;
  293. LCD_CAM.cam_ctrl1.cam_de_inv = 0;
  294. LCD_CAM.cam_ctrl1.cam_hsync_inv = 0;
  295. LCD_CAM.cam_ctrl1.cam_vsync_inv = 0;
  296. LCD_CAM.cam_ctrl1.cam_vh_de_mode_en = 0;
  297. LCD_CAM.cam_rgb_yuv.val = 0;
  298. #if CONFIG_CAMERA_CONVERTER_ENABLED
  299. if (config->conv_mode) {
  300. ret = ll_cam_converter_config(cam, config);
  301. if(ret != ESP_OK) {
  302. return ret;
  303. }
  304. }
  305. #endif
  306. LCD_CAM.cam_ctrl.cam_update = 1;
  307. LCD_CAM.cam_ctrl1.cam_start = 1;
  308. ret = ll_cam_dma_init(cam);
  309. return ret;
  310. }
  311. void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en)
  312. {
  313. LCD_CAM.lc_dma_int_clr.cam_vsync_int_clr = 1;
  314. if (en) {
  315. LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1;
  316. } else {
  317. LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 0;
  318. }
  319. }
  320. esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config)
  321. {
  322. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_pclk], PIN_FUNC_GPIO);
  323. gpio_set_direction(config->pin_pclk, GPIO_MODE_INPUT);
  324. gpio_set_pull_mode(config->pin_pclk, GPIO_FLOATING);
  325. gpio_matrix_in(config->pin_pclk, CAM_PCLK_IDX, false);
  326. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_vsync], PIN_FUNC_GPIO);
  327. gpio_set_direction(config->pin_vsync, GPIO_MODE_INPUT);
  328. gpio_set_pull_mode(config->pin_vsync, GPIO_FLOATING);
  329. gpio_matrix_in(config->pin_vsync, CAM_V_SYNC_IDX, cam->vsync_invert);
  330. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_href], PIN_FUNC_GPIO);
  331. gpio_set_direction(config->pin_href, GPIO_MODE_INPUT);
  332. gpio_set_pull_mode(config->pin_href, GPIO_FLOATING);
  333. gpio_matrix_in(config->pin_href, CAM_H_ENABLE_IDX, false);
  334. int data_pins[8] = {
  335. config->pin_d0, config->pin_d1, config->pin_d2, config->pin_d3, config->pin_d4, config->pin_d5, config->pin_d6, config->pin_d7,
  336. };
  337. for (int i = 0; i < 8; i++) {
  338. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[data_pins[i]], PIN_FUNC_GPIO);
  339. gpio_set_direction(data_pins[i], GPIO_MODE_INPUT);
  340. gpio_set_pull_mode(data_pins[i], GPIO_FLOATING);
  341. gpio_matrix_in(data_pins[i], CAM_DATA_IN0_IDX + i, false);
  342. }
  343. if (config->pin_xclk >= 0) {
  344. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_xclk], PIN_FUNC_GPIO);
  345. gpio_set_direction(config->pin_xclk, GPIO_MODE_OUTPUT);
  346. gpio_set_pull_mode(config->pin_xclk, GPIO_FLOATING);
  347. gpio_matrix_out(config->pin_xclk, CAM_CLK_IDX, false, false);
  348. }
  349. return ESP_OK;
  350. }
  351. esp_err_t ll_cam_init_isr(cam_obj_t *cam)
  352. {
  353. esp_err_t ret = ESP_OK;
  354. ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[0].pairs[cam->dma_num].rx_irq_id,
  355. ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | CAMERA_ISR_IRAM_FLAG,
  356. (uint32_t)&GDMA.channel[cam->dma_num].in.int_st, GDMA_IN_SUC_EOF_CH0_INT_ST_M,
  357. ll_cam_dma_isr, cam, &cam->dma_intr_handle);
  358. if (ret != ESP_OK) {
  359. ESP_LOGE(TAG, "DMA interrupt allocation of camera failed");
  360. return ret;
  361. }
  362. ret = esp_intr_alloc_intrstatus(ETS_LCD_CAM_INTR_SOURCE,
  363. ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | CAMERA_ISR_IRAM_FLAG,
  364. (uint32_t)&LCD_CAM.lc_dma_int_st.val, LCD_CAM_CAM_VSYNC_INT_ST_M,
  365. ll_cam_vsync_isr, cam, &cam->cam_intr_handle);
  366. if (ret != ESP_OK) {
  367. ESP_LOGE(TAG, "LCD_CAM interrupt allocation of camera failed");
  368. return ret;
  369. }
  370. return ESP_OK;
  371. }
  372. void ll_cam_do_vsync(cam_obj_t *cam)
  373. {
  374. gpio_matrix_in(cam->vsync_pin, CAM_V_SYNC_IDX, !cam->vsync_invert);
  375. ets_delay_us(10);
  376. gpio_matrix_in(cam->vsync_pin, CAM_V_SYNC_IDX, cam->vsync_invert);
  377. }
  378. uint8_t ll_cam_get_dma_align(cam_obj_t *cam)
  379. {
  380. return 16 << GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size;
  381. }
  382. static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){
  383. size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item;
  384. size_t line_width = cam->width * cam->in_bytes_per_pixel;
  385. size_t node_size = node_max;
  386. size_t nodes_per_line = 1;
  387. size_t lines_per_node = 1;
  388. // Calculate DMA Node Size so that it's divisable by or divisor of the line width
  389. if(line_width >= node_max){
  390. // One or more nodes will be requied for one line
  391. for(size_t i = node_max; i > 0; i=i-1){
  392. if ((line_width % i) == 0) {
  393. node_size = i;
  394. nodes_per_line = line_width / node_size;
  395. break;
  396. }
  397. }
  398. } else {
  399. // One or more lines can fit into one node
  400. for(size_t i = node_max; i > 0; i=i-1){
  401. if ((i % line_width) == 0) {
  402. node_size = i;
  403. lines_per_node = node_size / line_width;
  404. while((cam->height % lines_per_node) != 0){
  405. lines_per_node = lines_per_node - 1;
  406. node_size = lines_per_node * line_width;
  407. }
  408. break;
  409. }
  410. }
  411. }
  412. ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
  413. (unsigned) (node_size * cam->dma_bytes_per_item), (unsigned) nodes_per_line, (unsigned) lines_per_node);
  414. cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item;
  415. size_t dma_half_buffer_max = CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX / 2 / cam->dma_bytes_per_item;
  416. if (line_width > dma_half_buffer_max) {
  417. ESP_LOGE(TAG, "Resolution too high");
  418. return 0;
  419. }
  420. // Calculate minimum EOF size = max(mode_size, line_size)
  421. size_t dma_half_buffer_min = node_size * nodes_per_line;
  422. // Calculate max EOF size divisable by node size
  423. size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min;
  424. // Adjust EOF size so that height will be divisable by the number of lines in each EOF
  425. size_t lines_per_half_buffer = dma_half_buffer / line_width;
  426. while((cam->height % lines_per_half_buffer) != 0){
  427. dma_half_buffer = dma_half_buffer - dma_half_buffer_min;
  428. lines_per_half_buffer = dma_half_buffer / line_width;
  429. }
  430. // Calculate DMA size
  431. size_t dma_buffer_max = 2 * dma_half_buffer_max;
  432. if (cam->psram_mode) {
  433. dma_buffer_max = cam->recv_size / cam->dma_bytes_per_item;
  434. }
  435. size_t dma_buffer_size = dma_buffer_max;
  436. if (!cam->psram_mode) {
  437. dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
  438. }
  439. ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
  440. (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item),
  441. (unsigned) lines_per_half_buffer, (unsigned) (dma_buffer_size * cam->dma_bytes_per_item));
  442. cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
  443. cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
  444. cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
  445. return 1;
  446. }
  447. bool ll_cam_dma_sizes(cam_obj_t *cam)
  448. {
  449. cam->dma_bytes_per_item = 1;
  450. if (cam->jpeg_mode) {
  451. if (cam->psram_mode) {
  452. cam->dma_buffer_size = cam->recv_size;
  453. cam->dma_half_buffer_size = 1024;
  454. cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size;
  455. cam->dma_node_buffer_size = cam->dma_half_buffer_size;
  456. } else {
  457. cam->dma_half_buffer_cnt = 16;
  458. cam->dma_buffer_size = cam->dma_half_buffer_cnt * 1024;
  459. cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt;
  460. cam->dma_node_buffer_size = cam->dma_half_buffer_size;
  461. }
  462. } else {
  463. return ll_cam_calc_rgb_dma(cam);
  464. }
  465. return 1;
  466. }
  467. size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len)
  468. {
  469. // YUV to Grayscale
  470. if (cam->in_bytes_per_pixel == 2 && cam->fb_bytes_per_pixel == 1) {
  471. size_t end = len / 8;
  472. for (size_t i = 0; i < end; ++i) {
  473. out[0] = in[0];
  474. out[1] = in[2];
  475. out[2] = in[4];
  476. out[3] = in[6];
  477. out += 4;
  478. in += 8;
  479. }
  480. return len / 2;
  481. }
  482. // just memcpy
  483. memcpy(out, in, len);
  484. return len;
  485. }
  486. 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)
  487. {
  488. if (pix_format == PIXFORMAT_GRAYSCALE) {
  489. 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) {
  490. cam->in_bytes_per_pixel = 1; // camera sends Y8
  491. } else {
  492. cam->in_bytes_per_pixel = 2; // camera sends YU/YV
  493. }
  494. cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8
  495. } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) {
  496. #if CONFIG_CAMERA_CONVERTER_ENABLED
  497. switch (cam->conv_mode) {
  498. case YUV422_TO_YUV420:
  499. cam->in_bytes_per_pixel = 1.5; // for DMA receive
  500. cam->fb_bytes_per_pixel = 1.5; // frame buffer stores YUV420
  501. break;
  502. case YUV422_TO_RGB565:
  503. default:
  504. cam->in_bytes_per_pixel = 2; // for DMA receive
  505. cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
  506. break;
  507. }
  508. #else
  509. cam->in_bytes_per_pixel = 2; // for DMA receive
  510. cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
  511. #endif
  512. } else if (pix_format == PIXFORMAT_JPEG) {
  513. cam->in_bytes_per_pixel = 1;
  514. cam->fb_bytes_per_pixel = 1;
  515. } else {
  516. ESP_LOGE(TAG, "Requested format is not supported");
  517. return ESP_ERR_NOT_SUPPORTED;
  518. }
  519. return ESP_OK;
  520. }
  521. // implements function from xclk.c to allow dynamic XCLK change
  522. esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz)
  523. {
  524. LCD_CAM.cam_ctrl.cam_clkm_div_b = 0;
  525. LCD_CAM.cam_ctrl.cam_clkm_div_a = 0;
  526. LCD_CAM.cam_ctrl.cam_clkm_div_num = 160000000 / xclk_freq_hz;
  527. LCD_CAM.cam_ctrl.cam_clk_sel = 3;//Select Camera module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: no clock.
  528. LCD_CAM.cam_ctrl.cam_update = 1;
  529. return ESP_OK;
  530. }