159 lines
5.6 KiB
C++
Executable File
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 *) ®->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
|