#ifndef DCMI_HPP #define DCMI_HPP #include "dma.h" #include "global_variable.h" #include "reg_dcmi_gen.h" #include "stm32u575xx.h" struct dcmi_buffer { uint32_t *data; uint32_t length; uint32_t picture_length; // return the length of the picture (byte) }; class Dcmi { public: bool transfer = false; private: DCMI_TypeDef *dcmi; reg_dcmi_t *reg; Dma *dma = nullptr; void (*frame_callback)(uint32_t *buffer, uint32_t buffer_size) = nullptr; void (*error_callback)() = nullptr; dcmi_buffer buffer; public: explicit Dcmi(DCMI_TypeDef *_dcmi) { this->dcmi = _dcmi; reg = (reg_dcmi_t *) dcmi; } // void init(uint32_t *buf, uint32_t buf_size, bool jpeg = true, bool continuous = false, // bool vsync_active_high = false, bool hsync_active_high = false, // bool pclk_falling_edge = false) { // rcc_enable_dcmi_clock(dcmi); // nvic_enable_dcmi_irq(dcmi); // this->buffer = {buf, buf_size, 0}; // reg->cr.jpeg = jpeg; // reg->cr.cm = continuous; // reg->cr.vspol = vsync_active_high; // reg->cr.hspol = hsync_active_high; // reg->cr.pckpol = pclk_falling_edge; // } void init_2640(Dma *_dma, uint32_t *_buf, uint32_t buf_size) { init_new(_dma, _buf, buf_size, ll_low, ll_low, true); } void init_5640(Dma *_dma, uint32_t *_buf, uint32_t buf_size) { init_new(_dma, _buf, buf_size, ll_high, ll_high, true); } hal_status_e init_new(Dma *_dma, uint32_t *buf, uint32_t buffer_size, ll_state_e vsync_active_high = ll_low, ll_state_e hsync_active_high = ll_low, bool pclk_falling_edge = false) { rcc_enable_dcmi_clock(dcmi); nvic_enable_dcmi_irq(dcmi); this->dma = _dma; this->buffer.data = buf; this->buffer.length = buffer_size; reg->cr.jpeg = 1; reg->cr.cm = 0; reg->cr.vspol = vsync_active_high; reg->cr.hspol = hsync_active_high; reg->cr.pckpol = pclk_falling_edge; if (this->dma == nullptr) return HAL_ERROR; // initialize dma dma->init(86, DMA_DATA_WIDTH_32_BITS, DMA_DATA_WIDTH_32_BITS, LL_DISABLE, LL_ENABLE, DMA_TYPE_PREPHERIAL, DMA_TYPE_MEMORY, buffer_size * 5); return HAL_OK; } void capture_enable() { reg->cr.capture = 1; // enable capture // enable frame and error interrupt reg->ier.frame_ie = 1; // wait for FRAME_RIS } void capture(uint32_t *buffer, uint32_t buffer_size) { dma->start((uint32_t) &DCMI->DR, (uint32_t) buffer, 4 * buffer_size); reg->cr.enable = 1; reg->ier.frame_ie = reg->ier.err_ie = reg->ier.ovr_ie = 1; reg->cr.capture = 1; // enable capture. This will start the data transfer if received data transfer = true; } dcmi_buffer dcmi_get_buf() { return this->buffer; } hal_status_e capture_block() { dma->start((uint32_t) &DCMI->DR, (uint32_t) this->buffer.data, 4 * this->buffer.length); reg->cr.enable = 1; reg->cr.capture = 1; // while (reg->ris.frame_ris == 0 && reg->ris.err_ris == 0); // replace with wait for true // wait_for_true(reg->ris.frame_ris == 1 && reg->ris.err_ris == 0); reg->cr.capture = 0; dma->stop(); uint32_t dst = dma->get_dst_addr(); buffer.picture_length = dst - (uint32_t) buffer.data; // find the ff d9 uint8_t *data = (uint8_t *) buffer.data; if (data[0] != 0xff || data[1] != 0xd8) { return HAL_ERROR; } // check the header bool find_picture = false; for (uint32_t i = buffer.picture_length - 50; i < buffer.picture_length + 50; i++) { if (data[i] == 0xff && data[i + 1] == 0xd9) { buffer.picture_length = i + 2; find_picture = true; break; } } for(uint32_t i =0;i<4*buffer.length;i++){ if(data[i] == 0xff && data[i+1] == 0xd9){ buffer.picture_length = i+2; find_picture = true; break; } } if (!find_picture) { buffer.picture_length = 0; return HAL_ERROR; } return HAL_OK; } void capture_disable() { reg->cr.capture = 0; // disable capture // disable interrupt and clear interrupt flag reg->ier.frame_ie = reg->ier.err_ie = reg->ier.line_ie = reg->ier.ovr_ie = reg->ier.vsync_ie = 0; reg->icr.frame_isc = reg->icr.err_isc = reg->icr.line_isc = reg->icr.ovr_isc = reg->icr.vsync_isc = 1; reg->cr.enable = 1; } void dcmi_handler() { // clear ISR reg_dcmi_ris_t ris = *(reg_dcmi_ris_t *) ®->ris; dcmi->ICR |= DCMI_ICR_LINE_ISC | DCMI_ICR_FRAME_ISC | DCMI_ICR_OVR_ISC | DCMI_ICR_VSYNC_ISC | DCMI_ICR_ERR_ISC; if (ris.err_ris | ris.ovr_ris) { // error call back reg->cr.enable = 0; transfer = false; } if (ris.frame_ris) { transfer = false; // frame call back // uint32_t dst_addr = dma->get_dst_addr(); // uint32_t transfer_size = dst_addr - (uint32_t) buffer.data; // transfer_size = transfer_size * 4; // this->capture_block(); // frame_callback(buffer.data, transfer_size); // uint32_t transfer_size = dst_addr - (uint32_t) frame_callback((uint32_t *) dma->get_memory_address(), // dma->get_memory_size() / 4); reg->cr.enable = 0; } } }; #endif // DCMI_HPP