This repository has been archived on 2024-05-28. You can view files and clone it, but cannot push or open issues or pull requests.
2023-11-14 16:25:09 -05:00

159 lines
5.6 KiB
C++
Executable File

#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 *) &reg->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