rk3399_arm_lvds/capimage/MultiFrameCapture_8478_HL.cpp

1550 lines
63 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "MonoCapturer.h"
#include "config.h"
#include "applog.h"
#include "gvideoisp1.h"
#include "Gpio.h"
#include "DevUtil.h"
#include "FpgaComm.h"
#include "CorrectParam.h"
#include "correct_ultis.h"
#include "stringex.hpp"
#include "filetools.h"
#include "CImageMerge.h"
#include "jsonconfig.h"
#include "MultiFrameCapture_8478_HL.h"
#include "StopWatch.h"
#include "linux\sched.h"
#include "deviceconfig.h"
#define LOG_PATH "/usr/local/correct.log"
const uint32_t WIDTH_8478 = 1224;
FileTools ftm_cr_log(LOG_PATH);
static std::string loggername = "MultiFrameCapture_8478_HL";
static double radio = 1.0;
static int offsetStep1[12];
static int expStep1[2][3];
static int org_index = 0;
static void initStep1()
{
printf("initStep aaaaaaaaaaa \n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
expStep1[i][j] = 600;
}
}
for (int i = 0; i < 12; i++)
{
offsetStep1[i] = 256;
printf("offsetStep[%d]=%d \n", i, offsetStep1[i]);
}
}
MultiFrameCapture_8478_HL::MultiFrameCapture_8478_HL() : reset_pin(new GpioOut(50)),
fpgaLoad(new Gpio(70)),
fpga_conf_done(new Gpio(69)),
fpga_conf_initn(new Gpio(71)),
bcorrecting(false),
snapthread(1)
{
LOG_INIT();
fpga_conf_done->setDirection(Gpio::in);
fpgaComm.reset(new FpgaComm());
pimgdata_info = {0};
// fpga_reload();
// fpga_reset();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// fpgaComm->resetADC();
// fpgaComm->resetADC();
// fpgaComm->update();
video.reset(new VIDEO_CLASS());
fpgaComm->update(3);
// GetFpgaparam(0x01,0);
set_ADC_config_frequency(12);
init_adc_8478();
snapthread.enqueue([]{
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(5, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); });
}
MultiFrameCapture_8478_HL::~MultiFrameCapture_8478_HL()
{
if (video.get())
video.reset();
printf("Exit ~MultiFrameCapture_8478_HL() \n");
}
void MultiFrameCapture_8478_HL::open()
{
}
void MultiFrameCapture_8478_HL::open(HGScanConfig config, FPGAConfigParam_8478 fpgaparam)
{
fpgaComm->update(3);
uint32_t reg8 = 0, reg5 = 0, reg12 = 0, reg11 = 0, reg10 = 0, reg2 = 0;
fpgaComm->set_8478_type(true);
// fpgaComm->read(2,reg2);
// fpgaComm->write(2,(reg2&0xffffffe1)|0xc); // adc 配置 频率
set_ADC_config_frequency(12);
// init_adc_8478();
printf(" dpi = %d \n", config.g200params.dpi);
fpgaComm->read(11, reg11);
fpgaComm->write(11, (reg11 & 0xffffffc0) | 0x12);
// fpgaComm->write(13,0xdec0000);
fpgaComm->write(13, 0xce40000); // 旗标位 18 -27位
// fpgaComm->write(13,0xd680000);
fpgaComm->set_cis_type(true);
m_config = config;
m_fpgaparam = fpgaparam;
int dpi = config.g200params.dpi == 0x02 ? 2 : (config.g200params.dpi == 0x03 ? 3 : 1);
int mode = config.g200params.color;
int phyHeight = paperHeight[(PaperSize)config.g200params.paper];
if(m_gscancap.papertype == 52 || m_gscancap.papertype == 54) phyHeight = m_gscancap.maxszie_sanp_height;
int tdpi = config.g200params.dpi == 0x02 ? 300 : (config.g200params.dpi == 0x03 ? 600 : 200);
int pixheight = ((int)((phyHeight / 25.4 * tdpi + 2) / 3)) * 3;
if (fpgaparam.DpiMode == 0x10)
pixheight = pixheight * 180 / 100;
if (fpgaparam.DpiMode == 0x11)
pixheight = pixheight * 130 / 100;
frame_height = 300;
frame_count = ceil((mode == 0x01 ? pixheight * 3 : pixheight) / (float)(frame_height)); // 彩色配置fpga 高度要为目标图像高度的3倍
if (frame_height * frame_count > FPGA_MAX_HEIGHT_SUP)
frame_count = FPGA_MAX_HEIGHT_SUP / frame_height;
fpgaComm->read(15, m_fpgaversion);
int startsample = 0;
ModeFpga fpgamod = {
.colorMode = mode,
.dpi = m_config.g200params.dpi,
.led = 1,
.sample = startsample, // 256+39
.adcA = 0,
.adcB = 0,
.selftest = 0,
.sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 10138
fpgaComm->setRegs(0x01, *((int *)(&fpgamod)));
fpgaComm->setSample(startsample);
fpgaComm->enableLed(true);
fpgaComm->setEnTestCol(false);
fpgaComm->setEnTestBit(false);
set_LED_PTN_8478(config.g200params.color == false);
set_dpi_mode(config.g200params.dpi);
set_pixel_count_8478(fpgaparam.Sp / 3 / (config.g200params.color ? 3 : 1), config.g200params.color == false);
configFPGAParam(config.g200params.color, config.g200params.dpi);
configFPGAParam_digital_gain(config.g200params.color, config.g200params.dpi);
set_exp_8478_single(fpgaparam.ExposureF[0], fpgaparam.ExposureF[1], fpgaparam.ExposureF[2], fpgaparam.Sp / (config.g200params.color ? 3 : 1), true, config.g200params.color);
set_exp_8478_single(fpgaparam.ExposureB[0], fpgaparam.ExposureB[1], fpgaparam.ExposureB[2], fpgaparam.Sp / (config.g200params.color ? 3 : 1), false, config.g200params.color);
// set_exp_8478_single(1000,1000,1000,fpgaparam.Sp/(config.g200params.color?3:1),true,config.g200params.color);
// set_exp_8478_single(1000,1000,1000,fpgaparam.Sp/(config.g200params.color?3:1),false,config.g200params.color);
config.g200params.dpi == 3 ? set_EN_postion(0x54, 0x3a0) : set_EN_postion(0x54, 0x1f0);
// video->set_buf_count(std::min(frame_count,20u));
video->set_buf_count(std::min(100u,frame_count));
uint32_t video_w = (config.g200params.dpi == 0x03 ? WIDTH_8478 * 2 : WIDTH_8478);
if (config.g200params.dpi == 0x01)
video_w = video_w * 2 / 3;
video->open(video_w, frame_height * 2);
fpgaComm->setFrameHeight(frame_height);
printf("fpgaComm set height = %d \n", frame_height);
fpgaComm->read(8, reg8);
// fpgaComm->write(8,reg8|0x100); //行号 enable
fpgaComm->write(8, reg8 & 0xfffffeff); // 行号 disable
fpgaComm->read(5, reg5);
// fpgaComm->write(5,reg5|0x2000); //测试数据 白+黑 enable
fpgaComm->write(5, reg5 & 0xffffdfff); // 测试数据 白+黑 disable
fpgaComm->read(12, reg12);
// fpgaComm->write(12,reg5&0xfffff000+0x97e); //帧间隔延迟 >=22.5us
// fpgaComm->write(12,reg5&0xe000e000+0xfa0067e); //帧间隔延迟 >=22.5us
// fpgaComm->write(12,0x04e20400); //0x494e491 0x79de496 范围 0-12 16-28 (16-28 > 0-12)
fpgaComm->read(10, reg10);
fpgaComm->write(12, 0x00200010); // 58us 300*600 多帧
fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧
fpgaComm->setFrameNum(1);
fpgaComm->capture(); // abort first frame
video->read_frame(1000);
fpgaComm->setFrameNum(frame_count);
fpgaComm->update(3);
// initLut(fpgaparam.LutPath, config.g200params.color);
// initLut(config.g200params.is_textcorrect?fpgaparam.LutPath:fpgaparam.TextLutPath,config.g200params.color);
// initLut(fpgaparam.TextLutPath, config.g200params.color);
init_lutdate();
// init_imagedatabuffer();
}
void MultiFrameCapture_8478_HL::init_lutdate()
{
DeviceConfig::Gray_Apply gray_;
gray_.value = Get_static_deviceconfig().GetParam().gray_param;
std::string lutpath = m_config.g200params.is_textcorrect ? m_fpgaparam.LutPath : m_fpgaparam.TextLutPath;
if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_clr == 1 && m_config.g200params.color == true))
lutpath = "/usr/local/huago/Graylut200clr.bmp";
else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_clr == 1 && m_config.g200params.color == true))
lutpath = "/usr/local/huago/Graylut300clr.bmp";
else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_clr == 1 && m_config.g200params.color == true))
lutpath = "/usr/local/huago/Graylut600clr.bmp";
else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_clr == 1 && m_config.g200params.color == true))
lutpath = "/usr/local/huago/Graylutslow_moireclr.bmp";
else if ((m_fpgaparam.DpiMode == 17) && (gray_.Param_Setting.en_slow_300_clr == 1 && m_config.g200params.color == true))
lutpath = "/usr/local/huago/Graylutslow_moire300clr.bmp";
else if ((m_fpgaparam.DpiMode == 32) && (gray_.Param_Setting.en_long_Manuscript_200_clr == 1 && m_config.g200params.color == true))
lutpath = "/usr/local/huago/GraylutLong_Manuscript200clr.bmp";
else if ((m_fpgaparam.DpiMode == 33) && (gray_.Param_Setting.en_long_Manuscript_300_clr == 1 && m_config.g200params.color == true))
lutpath = "/usr/local/huago/GraylutLong_Manuscript300clr.bmp";
else if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_gray == 1 && m_config.g200params.color == false))
lutpath = "/usr/local/huago/Graylut200gray.bmp";
else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_gray == 1 && m_config.g200params.color == false))
lutpath = "/usr/local/huago/Graylut300gray.bmp";
else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_gray == 1 && m_config.g200params.color == false))
lutpath = "/usr/local/huago/Graylut600gray.bmp";
else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_gray == 1 && m_config.g200params.color == false))
lutpath = "/usr/local/huago/Graylutslow_moiregray.bmp";
else if ((m_fpgaparam.DpiMode == 17) && (gray_.Param_Setting.en_slow_300_gray == 1 && m_config.g200params.color == false))
lutpath = "/usr/local/huago/Graylutslow_moire300gray.bmp";
else if ((m_fpgaparam.DpiMode == 32) && (gray_.Param_Setting.en_long_Manuscript_200_gray == 1 && m_config.g200params.color == false))
lutpath = "/usr/local/huago/GraylutLong_Manuscript200gray.bmp";
else if ((m_fpgaparam.DpiMode == 33) && (gray_.Param_Setting.en_long_Manuscript_300_gray == 1 && m_config.g200params.color == false))
lutpath = "/usr/local/huago/GraylutLong_Manuscript300gray.bmp";
initLut(lutpath, m_config.g200params.color);
}
void MultiFrameCapture_8478_HL::close()
{
if (video.get())
video->close();
// if(pimgdata_info.pdata) free(pimgdata_info.pdata);
// pimgdata_info.pdata = nullptr;
pimgdata_info.offset = pimgdata_info.frame_count = pimgdata_info.img_h = pimgdata_info.img_w = 0;
printf("pimgdata_ free !!!!!\n");
// fpgaComm->resetADC();
// fpga_reload();
}
void MultiFrameCapture_8478_HL::Fpga_regsAccess_reset(bool enable)
{
if (fpgaComm.get())
fpgaComm->regsAccess_reset(enable);
if (enable)
{
set_ADC_config_frequency(12);
init_adc_8478();
}
}
void MultiFrameCapture_8478_HL::start()
{
if (video.get())
video->start();
}
void MultiFrameCapture_8478_HL::MultiFrameCapture_8478_HL::stop()
{
if (video.get())
video->stop();
}
bool MultiFrameCapture_8478_HL::is_runing()
{
return false;
}
// static void printlog(std::string str)
// {
// std::ofstream o("/root/log.txt",std::ios::app|std::ios::binary);
// if(o.is_open())
// {
// o << str <<std::endl;
// o.close();
// }
// }
void MultiFrameCapture_8478_HL::snap()
{
fpgaComm->capture();
printf("snap start !!!!! \n");
b_stop_snap = false;
pimgdata_info.offset = pimgdata_info.frame_count =
pimgdata_info.img_h = pimgdata_info.img_w = 0;
snap_fu = snapthread.enqueue([this]
{
auto snap_func = [this](int height,int width, int channels, bool last_frame, unsigned int frame_index)
{
StopWatch sw;
void *data = video->read_frame(500);
if (data)
{
update_imgdatainfo(data,height,width);
printf("memcpy date size = %d times = %f index = %d \n",height*width,sw.elapsed_ms(),frame_index);
}
else
{
printf("!!!!!!!!!! error read frame losted, i = %d \n", frame_index);
//printlog("!!!!!!!!!! error read frame losted");
}
};
int width = WIDTH_8478*3*2*(m_config.g200params.dpi == 3 ? 2 : 1)*(m_config.g200params.color ? 3 :1);
if(m_config.g200params.dpi == 1)
width = width *2/3;
int height = frame_height/(m_config.g200params.color ? 3 :1);
for (int i = 1; i <= frame_count; i++)
{
curr_frame_snap_index = i;
snap_func(height,width, 0, (i == frame_count), i);
if (b_stop_snap)
{
int snaped_frame_count = fpgaComm->getFrame_counter_val();
printf("!!!!!!!!!! revsed frame count = %d i = %d \n", snaped_frame_count, i);
if (snaped_frame_count > i && snaped_frame_count > 0) // 正常情况下 snaped_frame_count 一定大于0
{
int reversed_frame_count = snaped_frame_count - i;
for (int j = 1; j <= reversed_frame_count; j++)
{
curr_frame_snap_index =j+i;
snap_func(height, width,0, ((i + j) == reversed_frame_count), i + j);
}
}
break; // 跳出当前读取多帧循环
}
}
printf("snap end !!!!! \n"); });
}
void MultiFrameCapture_8478_HL::snap(frame_data_info info)
{
printf("snap start !!!!! \n");
b_stop_snap = false;
info.offset = info.frame_count = info.img_h = info.img_w = 0;
snap_fu = snapthread.enqueue([this, info]{
frame_data_info frame_info {0};
frame_info.pdata = info.pdata;
frame_info.total = info.total;
auto snap_func = [this,&frame_info](int height,int width, int channels, bool last_frame, unsigned int frame_index)
{
StopWatch sw;
void *data = video->read_frame(500);
if (data)
{
update_imgdatainfo(data,frame_info,height,width);
printf("memcpy date size = %d times = %f index = %d \n",height*width,sw.elapsed_ms(),frame_index);
}
else
printf("!!!!!!!!!! error read frame losted, i = %d \n", frame_index);
};
int width = WIDTH_8478*3*2*(m_config.g200params.dpi == 3 ? 2 : 1)*(m_config.g200params.color ? 3 :1);
if(m_config.g200params.dpi == 1)
width = width *2/3;
int height = frame_height/(m_config.g200params.color ? 3 :1);
for (int i = 1; i <= frame_count; i++)
{
curr_frame_snap_index = i;
snap_func(height,width, 0, (i == frame_count), i);
if (b_stop_snap)
{
int snaped_frame_count = fpgaComm->getFrame_counter_val();
printf("!!!!!!!!!! revsed frame count = %d i = %d \n", snaped_frame_count, i);
if (snaped_frame_count > i && snaped_frame_count > 0) // 正常情况下 snaped_frame_count 一定大于0
{
int reversed_frame_count = snaped_frame_count - i;
for (int j = 1; j <= reversed_frame_count; j++)
{
curr_frame_snap_index = i+j;
snap_func(height, width,0, ((i + j) == reversed_frame_count), i + j);
}
}
break; // 跳出当前读取多帧循环
}
}
pimgdata_info = frame_info;
printf("snap end !!!!! \n"); });
}
cv::Size MultiFrameCapture_8478_HL::frame_data_size()
{
return {2 * this->width() * (m_config.g200params.color ? 3 : 1), frame_height / (m_config.g200params.color ? 3 : 1) * frame_count};
}
void MultiFrameCapture_8478_HL::stopsnap()
{
b_stop_snap = true;
if(snap_fu.valid()) snap_fu.get();
}
int MultiFrameCapture_8478_HL::getautosizeheight()
{
unsigned int val;
unsigned int reg8 = 0;
fpgaComm->read(8, reg8);
// std::cout << "1 reg[8]:" << string_format("0x%08x", reg8) << std::endl;
// fpgaComm->update(4);
fpgaComm->read(14, val);
int regv = val;
val &= 0x0000ffff;
// std::cout << string_format("ONE height = %d reg[14] = %d \n", val, regv);
// fpgaComm->update(5);
fpgaComm->write(8, reg8 & 0xfffffff7);
// std::cout << string_format("ONE reg[8] = %d \n", reg8 & 0xfffffff7);
std::this_thread::sleep_for(std::chrono::milliseconds(5));
// fpgaComm->update(6);
fpgaComm->read(14, val);
regv = val;
val &= 0x0000ffff;
fpgaComm->read(8, reg8);
// std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl;
std::cout << string_format("TWO height = %d reg[14] = %d \n", val, regv);
std::this_thread::sleep_for(std::chrono::milliseconds(5));
fpgaComm->write(8, reg8 | 0x8);
// fpgaComm->write(8,0x02260008);
// fpgaComm->update(7);
// fpgaComm->read(8, reg8);
// std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl;
return val;
// return fpgaComm->getFrameHeight();
}
void MultiFrameCapture_8478_HL::set_size(int width, int height)
{
if (video.get())
video->set_size(width, height);
}
void MultiFrameCapture_8478_HL::set_sp(int sp)
{
fpgaComm->setSp(sp);
}
void *MultiFrameCapture_8478_HL::readFrame(int timeout)
{
return video->read_frame(timeout);
}
cv::Mat MultiFrameCapture_8478_HL::read_one_frame()
{
fpgaComm->setFrameNum(1);
fpgaComm->capture();
void *data = video->read_frame(1000);
fpgaComm->setFrameNum(frame_count);
if (data)
{
int width = WIDTH_8478 * 3 * 2 * (m_config.g200params.dpi == 3 ? 2 : 1) * (m_config.g200params.color ? 3 : 1);
if (m_config.g200params.dpi == 1)
width = width * 2 / 3;
int height = frame_height / (m_config.g200params.color ? 3 : 1);
cv::Mat mat(height, width, CV_8UC1, data);
return merge_8478(mat, m_config.g200params.color, 0);
}
else
return cv::Mat();
}
frame_data_info MultiFrameCapture_8478_HL::ReadMultiFrame(int state)
{
printf(" ReadMultiFrame state : %d \n", state);
if (state & 1)
b_stop_snap = true;
if (snap_fu.valid())
snap_fu.get();
if ((state & 0x2) || (!pimgdata_info.pdata))
return {0};
return pimgdata_info;
}
void MultiFrameCapture_8478_HL::set_gain(int ix, int val)
{
for (int i = 0; i < 6; i++)
{
if (ix)
fpgaComm->setAGain(i, val);
else
fpgaComm->setBGain(i, val);
}
}
void MultiFrameCapture_8478_HL::set_offset(int ix, int val)
{
for (int i = 0; i < 6; i++)
{
if (ix)
fpgaComm->setAOffset(i, val);
else
fpgaComm->setBOffset(i, val);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
void MultiFrameCapture_8478_HL::set_expo(int ix, int val)
{
switch (ix)
{
case 0:
fpgaComm->setAExposureR(val);
break;
case 1:
fpgaComm->setAExposureG(val);
break;
case 2:
fpgaComm->setAExposureB(val);
break;
case 3:
fpgaComm->setBExposureR(val);
break;
case 4:
fpgaComm->setBExposureG(val);
break;
case 5:
fpgaComm->setBExposureB(val);
break;
default:
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::shared_ptr<IRegsAccess> MultiFrameCapture_8478_HL::regs()
{
return fpgaComm;
}
void MultiFrameCapture_8478_HL::reset()
{
fpga_reset();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
fpgaComm->resetADC();
// fpgaComm->setDelayTime(0X3e8);
// fpgaComm->setRegs(0x00, fpgaComm->getRegs(0x00));
// fpgaComm->setRegs(0x01, fpgaComm->getRegs(0x01));
}
int MultiFrameCapture_8478_HL::width()
{
// int dpi = fpgaComm->getDpi();
// int channel = 1;
// int width = dpi == 0x02 ? 1296 * channel : (dpi == 0x03 ? (2592 * channel) : (864 * channel));
// printf("get width = %d \n", width);
// return width;
uint32_t width = WIDTH_8478 * 3 * (m_config.g200params.dpi == 3 ? 2 : 1);
return m_config.g200params.dpi == 1 ? (width * 2 / 3) : width;
}
int MultiFrameCapture_8478_HL::height()
{
return fpgaComm->getFrameHeight();
}
int MultiFrameCapture_8478_HL::color()
{
return fpgaComm->getColorMode() ? 16 : 0;
}
void MultiFrameCapture_8478_HL::init_autocorrect(int colormode)
{
std::thread t_correctthread = std::thread(&MultiFrameCapture_8478_HL::correctcolor, this, colormode);
t_correctthread.detach();
// if(t_correctthread.joinable())
// t_correctthread.join();
}
void MultiFrameCapture_8478_HL::configFPGAParam(int mode, int dpi)
{
printf("dpi = %d mode = %d \n", dpi, mode);
FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode);
for (int i = 0; i < 9; i++)
{
set_digital_offset_8478(i, fpgaparam.OffsetF_R[i], true, 0);
set_digital_offset_8478(i, fpgaparam.OffsetF_G[i], true, 1);
set_digital_offset_8478(i, fpgaparam.OffsetF_B[i], true, 2);
set_digital_offset_8478(i, fpgaparam.OffsetB_R[i], false, 0);
set_digital_offset_8478(i, fpgaparam.OffsetB_G[i], false, 1);
set_digital_offset_8478(i, fpgaparam.OffsetB_B[i], false, 2);
printf("\n OffsetF_R[%d] = %d OffsetF_G[%d] = %d OffsetF_B[%d] = %d ", i, fpgaparam.OffsetF_R[i],
i, fpgaparam.OffsetF_G[i], i, fpgaparam.OffsetF_B[i]);
printf("\n OffsetB_R[%d] = %d OffsetB_G[%d] = %d OffsetB_B[%d] = %d ", i, fpgaparam.OffsetB_R[i],
i, fpgaparam.OffsetB_G[i], i, fpgaparam.OffsetB_B[i]);
}
}
void MultiFrameCapture_8478_HL::configFPGAParam_digital_gain(int mode, int dpi)
{
FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode);
for (int i = 0; i < 9; i++)
{
set_digital_gain_8478(i, fpgaparam.GainF_R[i], true, 0);
set_digital_gain_8478(i, fpgaparam.GainF_G[i], true, 1);
set_digital_gain_8478(i, fpgaparam.GainF_B[i], true, 2);
set_digital_gain_8478(i, fpgaparam.GainB_R[i], false, 0);
set_digital_gain_8478(i, fpgaparam.GainB_G[i], false, 1);
set_digital_gain_8478(i, fpgaparam.GainB_B[i], false, 2);
printf("\n GainF_R[%d] = %d GainF_G[%d] = %d GainF_B[%d] = %d ", i, fpgaparam.GainF_R[i],
i, fpgaparam.GainF_G[i], i, fpgaparam.GainF_B[i]);
printf("\n GainB_R[%d] = %d GainB_G[%d] = %d GainB_B[%d] = %d ", i, fpgaparam.GainB_R[i],
i, fpgaparam.GainB_G[i], i, fpgaparam.GainB_B[i]);
}
}
void MultiFrameCapture_8478_HL::openDevice(int dpi, int mode)
{
FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode);
if (dpi == 0x10 || dpi == 0x20)
dpi = 1;
if (dpi == 0x11 || dpi == 0x21)
dpi = 2;
int channelwidth = dpi == 0x02 ? WIDTH_8478 : (dpi == 0x03 ? WIDTH_8478 * 2 : WIDTH_8478 * 2 / 3);
int channels = mode == 0x01 ? 3 : 1;
int width = channelwidth * channels;
fpgaComm->set_8478_type(true);
set_ADC_config_frequency(12);
init_adc_8478();
uint32_t reg11 = 0, reg8 = 0, reg5 = 0, reg10 = 0, reg12 = 0;
fpgaComm->read(11, reg11);
fpgaComm->write(11, (reg11 & 0xffffffc0) | 0x12);
// fpgaComm->write(13,0xdec0000);
fpgaComm->write(13, 0xce40000); // 旗标位 18 -27位
// fpgaComm->write(13,0xd680000);
video->set_buf_count(10);
fpgaComm->set_cis_type(true);
dpi == 3 ? set_EN_postion(0x54, 0x3a0) : set_EN_postion(0x54, 0x1f0);
set_LED_PTN_8478(mode == false);
set_dpi_mode(dpi);
set_pixel_count_8478(fpgaparam.Sp / 3 / (mode ? 3 : 1), mode == false);
frame_height = 300;
frame_count = 1; // 最后一帧丢帧,多采集一帧防止图像数据缺失
fpgaComm->read(15, m_fpgaversion);
int startsample = 0;
ModeFpga fpgamod = {
.colorMode = mode,
.dpi = dpi,
.led = 1,
.sample = startsample, // 256+39
.adcA = 0,
.adcB = 0,
.selftest = 0,
.sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 10138
fpgaComm->setRegs(0x01, *((int *)(&fpgamod)));
fpgaComm->setSample(startsample);
fpgaComm->enableLed(true);
fpgaComm->setEnTestCol(false);
fpgaComm->setEnTestBit(false);
uint32_t video_w = dpi == 0x03 ? WIDTH_8478 * 2 : (dpi == 1 ? WIDTH_8478 * 2 / 3 : WIDTH_8478);
video->open(video_w, frame_height * 2);
fpgaComm->setFrameNum(frame_count);
fpgaComm->setFrameHeight(frame_height);
printf("fpgaComm set height = %d \n", frame_height);
fpgaComm->read(8, reg8);
// fpgaComm->write(8,reg8|0x100); //行号 enable
fpgaComm->write(8, reg8 & 0xfffffeff); // 行号 disable
fpgaComm->read(5, reg5);
// fpgaComm->write(5,reg5|0x2000); //测试数据 白+黑 enable
fpgaComm->write(5, reg5 & 0xffffdfff); // 测试数据 白+黑 disable
fpgaComm->read(12, reg12);
fpgaComm->read(10, reg10);
// if(dpi == 3){
// fpgaComm->write(10,0x03b0037a); //120 us 600*600 多帧
// fpgaComm->write(12,0x02000100); //120 us 600*600 多帧
// }
// else
{
fpgaComm->write(12, 0x00200010); // 58us 300*600 多帧
fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧
}
configFPGAParam(mode, dpi);
configFPGAParam_digital_gain(mode,dpi);
fpgaComm->update(3);
fpgaComm->capture(); // abort first frame
for (int i = 0; i < frame_count; i++)
video->read_frame(500);
}
void MultiFrameCapture_8478_HL::creatcorrectconfig(int dpi, int mode)
{
printf(" opendevice");
openDevice(dpi, mode);
printf(" opendevice end ");
bool isDone = false;
int i = 1;
initStep1();
set_led_off();
while (!isDone) // 先暗场
{
std::string log = "==============================第" + std::to_string(i) + "次===============================";
ftm_cr_log.append_log(log);
configFPGAParam(mode, dpi);
configFPGAParam_digital_gain(mode,dpi);
ftm_cr_log.append_log(log);
std::this_thread::sleep_for(std::chrono::milliseconds(3));
fpgaComm->capture();
std::this_thread::sleep_for(std::chrono::milliseconds(3));
isDone = saveLutImg(dpi, mode, true); // 0 color_black 1 color_white 2 gray_balck 3 gray_white
i++;
}
i = 1;
isDone = false;
initStep1();
while (!isDone) // 后明场
{
FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode);
set_exp_8478_single(fpgaparam.ExposureF[0], fpgaparam.ExposureF[1], fpgaparam.ExposureF[2], fpgaparam.Sp / (mode ? 3 : 1), true, mode);
set_exp_8478_single(fpgaparam.ExposureB[0], fpgaparam.ExposureB[1], fpgaparam.ExposureB[2], fpgaparam.Sp / (mode ? 3 : 1), false, mode);
std::string log = "==============================第" + std::to_string(i) + "次===============================";
ftm_cr_log.append_log(log);
std::this_thread::sleep_for(std::chrono::milliseconds(3));
fpgaComm->capture();
std::this_thread::sleep_for(std::chrono::milliseconds(3));
isDone = saveLutImg(dpi, mode, false);
i++;
}
printf("creatcorrectconfig %s \n", (mode == IMAGE_COLOR ? " Color" : " Gray"));
// creatLUTData(dpi, mode);
video->close();
}
static int savelutindex = 0;
bool MultiFrameCapture_8478_HL::saveLutImg(int dpi, int mode, bool black)
{
FPGAConfigParam_8478 param = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode);
if (dpi == 0x10 || dpi == 0x20)
dpi = 1;
if (dpi == 0x11 || dpi == 0x21)
dpi = 2;
int offset_indexs[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8};
int width = WIDTH_8478 * 3 * 2 * (dpi == 3 ? 2 : 1) * (mode ? 3 : 1);
if (dpi == 1)
width = width * 2 / 3;
int height = frame_height / (mode ? 3 : 1);
bool isNeedSave = true;
std::string log;
void *data = video->read_frame(10000);
if (data == NULL)
{
isNeedSave = false;
log = "WARNNING WARNNING WARNNING FAILDED TO READ IMAGE DATA !!!!!!!!!!!!!!!!!!!\r\n";
ftm_cr_log.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
return isNeedSave;
}
cv::Mat src(height, width, CV_8UC1, data);
// cv::imwrite(std::to_string(savelutindex++) + ".jpg", src);
CImageMerge t_marge;
// cv::Mat mrgmat = t_marge.MergeImage(mode == 0x01, src, dstwidth, height,m_fpgaversion);
cv::Mat mrgmat = merge_8478(src, mode, 0);
mrgmat = mrgmat(cv::Rect(0, 10, mrgmat.cols, mrgmat.rows - 20));
// cv::imwrite("correct.bmp",mrgmat);
// return false;
if (black) // 暗场
{
double offValues_R[18]{0};
double offValues_G[18]{0};
double offValues_B[18]{0};
std::vector<bool> bflags(2 * 9 * (mode ? 3 : 1), false);
for (volatile int n = 0; n < 2; n++)
{
cv::Mat img = mrgmat(cv::Rect(mrgmat.cols * n / 2, 10, mrgmat.cols / 2, mrgmat.rows - 10)).clone();
int offset_total = 0;
for (volatile int s = 0; s < 9; s++) //
{
int k = n * 9 + s;
int offset_wdth;
if ((k == 8) || (k == 17))
offset_wdth = dpi == 0x03 ? 432 : (dpi == 0x02 ? 216 : 144);
else
offset_wdth = dpi == 0x03 ? 864 : (dpi == 0x02 ? 432 : 288);
cv::Scalar mean = cv::mean(img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)));
if (mode)
{
offValues_R[k] = mean.val[0];
offValues_G[k] = mean.val[1];
offValues_B[k] = mean.val[2];
// auto tmp_mat = img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10));
// offValues_R[k] = (*std::min_element(tmp_mat.begin<cv::Vec3b>(),tmp_mat.end<cv::Vec3b>(),
// [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[0] < b[0]; }))[0];
// offValues_G[k] = (*std::min_element(tmp_mat.begin<cv::Vec3b>(),tmp_mat.end<cv::Vec3b>(),
// [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[1] < b[1]; }))[1];
// offValues_B[k] = (*std::min_element(tmp_mat.begin<cv::Vec3b>(),tmp_mat.end<cv::Vec3b>(),
// [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[2] < b[2]; }))[2];
printf("\noffValues[%d] R = %f G = %f B= %f", k, offValues_R[k], offValues_G[k], offValues_B[k]);
}
else{
offValues_R[k] = offValues_G[k] = offValues_B[k] = mean.val[0];
// auto tmp_mat = img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10));
// offValues_R[k] = offValues_G[k] = offValues_B[k] = *std::min_element(tmp_mat.begin<std::uint8_t>(),
// tmp_mat.end<std::uint8_t>(), [](std::uint8_t a, std::uint8_t b) -> bool{ return a < b; });
printf("\noffValues[%d] = %f", k, offValues_R[k]);
}
offset_total += offset_wdth;
}
}
// std::string clrmode = (mode == 0x01 ? "彩色" : " 灰度");
// log = "开始" + clrmode + "暗场校正 \n";
for (volatile int s = 0; s < 2; s++)
{
int offsets_R[9]{0}, offsets_G[9]{0}, offsets_B[9]{0}; // = (int *)(s == 0 ? &param.OffsetF[0] : &param.OffsetB[0]);
memcpy(offsets_R, (s == 0 ? &param.OffsetF_R[0] : &param.OffsetB_R[0]), sizeof(param.OffsetF_R));
memcpy(offsets_G, (s == 0 ? &param.OffsetF_G[0] : &param.OffsetB_G[0]), sizeof(param.OffsetF_G));
memcpy(offsets_B, (s == 0 ? &param.OffsetF_B[0] : &param.OffsetB_B[0]), sizeof(param.OffsetF_B));
if (mode == IMAGE_GRAY)
{
for (volatile int j = 0; j < 9; j++)
{
int k = s * 9 + j;
double diff = BLACK_DIFF(offValues_R[k]);
//double diff = 3 - offValues_R[k];
double step = radio * diff;
int preStep = offsetStep1[k];
if (step < 1 && step > 0)
step = 1;
if (step < 0 && step > -1)
step = -1;
// FMT_STEP(step);
bool isMinStep = abs(step) == 1 && step == offsetStep1[k];
bool isOutBounds = offsets_R[j] >= 512 && step > 0;
isOutBounds |= offsets_R[j] <= 0 && step < 0;
log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues_R[k]) + ";offset:" + std::to_string(offsets_R[j]) + ";step:" + std::to_string(step) + "\r\n";
if (isOutBounds)
log += "" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n";
//else if (abs(step) > 1 || isMinStep)
else if (abs(step) > 1)
{
offsetStep1[k] = (int)(step);
offsets_R[offset_indexs[k]] += step;
log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n";
if (offsets_R[offset_indexs[k]] < 1)
offsets_R[offset_indexs[k]] = 1;
if (offsets_R[offset_indexs[k]] > 512)
offsets_R[offset_indexs[k]] = 512;
// isNeedSave = false;
bflags[k] = false;
}
else
{
bflags[k] = true;
// printf("channel[%d] black correct done\n",k);
}
log += (s == 0 ? "彩色正面" : "彩色背面");
log += "偏移值:" + std::to_string(offsets_R[0]) + "," + std::to_string(offsets_R[1]) + "," + std::to_string(offsets_R[2]) + "," +
std::to_string(offsets_R[3]) + "," + std::to_string(offsets_R[4]) + "," + std::to_string(offsets_R[5]) + "," + std::to_string(offsets_R[6]) +
"," + std::to_string(offsets_R[7]) + "," + std::to_string(offsets_R[8]) + "\r\n";
// printf("\n%s",log.c_str());
// log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n");
ftm_cr_log.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
log = "";
}
memcpy(offsets_G, offsets_R, sizeof(offsets_R));
memcpy(offsets_B, offsets_R, sizeof(offsets_R));
}
else
{
double offValues[18]{0};
int offsets[9]{0};
for (int color = 0; color < 3; color++)
{
memcpy(offValues, color == 0 ? offValues_R : (color == 1 ? offValues_G : offValues_B), sizeof(offValues));
memcpy(offsets, color == 0 ? offsets_R : (color == 1 ? offsets_G : offsets_B), sizeof(offsets));
for (volatile int j = 0; j < 9; j++)
{
int k = s * 9 + j;
double diff = BLACK_DIFF(offValues[k]);
// double diff = 3 - offValues[k];
double step = radio * diff;
int preStep = offsetStep1[k];
if (step < 1 && step > 0)
step = 1;
if (step < 0 && step > -1)
step = -1;
// FMT_STEP(step);
bool isMinStep = abs(step) == 1 && step == offsetStep1[k];
bool isOutBounds = offsets[j] >= 512 && step > 0;
isOutBounds |= offsets[j] <= 0 && step < 0;
log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n";
if (isOutBounds)
log += "" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n";
//else if (abs(step) > 1 || isMinStep)
else if (abs(step) > 1)
{
offsetStep1[k] = (int)(step);
offsets[offset_indexs[k]] += step;
log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n";
if (offsets[offset_indexs[k]] < 1)
offsets[offset_indexs[k]] = 1;
if (offsets[offset_indexs[k]] > 512)
offsets[offset_indexs[k]] = 512;
// isNeedSave = false;
bflags[18 * color + k] = false;
}
else
{
bflags[18 * color + k] = true;
// printf("channel[%d] black correct done\n",k);
}
log += (s == 0 ? "彩色正面" : "彩色背面");
log += "偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," +
std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "," + std::to_string(offsets[6]) +
"," + std::to_string(offsets[7]) + "," + std::to_string(offsets[7]) + "\r\n";
// log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n");
// printf("\n%s",log.c_str());
ftm_cr_log.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
log = "";
}
memcpy(color == 0 ? offValues_R : (color == 1 ? offValues_G : offValues_B), offValues, sizeof(offValues));
memcpy(color == 0 ? offsets_R : (color == 1 ? offsets_G : offsets_B), offsets, sizeof(offsets));
}
}
memcpy((s == 0 ? &param.OffsetF_R[0] : &param.OffsetB_R[0]), offsets_R, sizeof(param.OffsetF_R));
memcpy((s == 0 ? &param.OffsetF_G[0] : &param.OffsetB_G[0]), offsets_G, sizeof(param.OffsetF_G));
memcpy((s == 0 ? &param.OffsetF_B[0] : &param.OffsetB_B[0]), offsets_B, sizeof(param.OffsetF_B));
}
for (int i = 0; i < bflags.size(); i++)
{
if (!bflags[i])
isNeedSave = false;
printf(" b_flags [%d] = %s ",i,bflags[i]?"true":"false");
}
if (isNeedSave)
{
printf("Save LUT image path :%s \n", param.Flat_BwPath.c_str());
log = "暗场校正完成 \r\n";
if (m_captureCallback)
m_captureCallback(mode, log);
// log ="";
imwrite(param.Flat_BwPath, mrgmat);
}
}
else // 明场
{
radio = 1.0;
if (mode == IMAGE_COLOR)
{
double values[2][3];
cv::Scalar a = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows)));
cv::Scalar b = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows)));
for (int j = 0; j < 3; j++)
{
values[0][j] = a.val[2 - j];
values[1][j] = b.val[2 - j];
}
printf("\n mean F_R = %f F_G = %f F_B = %f B_R = %f B_G = %f B_B = %f ", values[0][0], values[0][1], values[0][2],
values[1][0], values[1][1], values[1][2]);
log = "开始彩色明场校正 \r\n";
if (m_captureCallback)
m_captureCallback(mode, log);
for (int s = 0; s < 2; s++)
{
int exposures[3]; // = (int *)(s == 0 ? param.ExposureF : param.ExposureB);
memcpy(exposures, (s == 0 ? &param.ExposureF[0] : &param.ExposureB[0]), sizeof(param.ExposureB));
for (int x = 0; x < 3; x++)
{
int k = (3 * s + x);
int diff = LIGHT_DIFF(param.MaxBright, *((double *)values + k));
log += " 明场:" + std::to_string(k) + ";diff" + std::to_string(diff) + "\r\n";
// if(abs(diff) > 30)
// radio = 2;
// else
// radio = 1;
double step = diff * radio;
int preStep = *((int *)expStep + k);
if (step * preStep < 0)
{
step = 0 - preStep / 2;
}
if (step < 1 && step > 0)
step = 1;
if (step < 0 && step > -1)
step = -1;
bool isMinStep = abs(step) == 1 && step == *((int *)expStep + k);
bool isOutBounds = exposures[x] >= (param.Sp / 3 / (mode ? 3 : 1) - 15) && step > 0;
isOutBounds |= exposures[x] <= 0 && step < 0;
if (isOutBounds)
log += "" + std::to_string(x) + "个明场校正异常 \r\n";
else if (abs(diff) >= 1 || isMinStep)
{
*((int *)expStep + k) = (int)(step);
exposures[x] += step;
if (exposures[x] > (param.Sp / 3 / (mode ? 3 : 1) - 15))
{
exposures[x] = (param.Sp / 3 / (mode ? 3 : 1) - 15);
}
if (exposures[x] <= 0)
exposures[x] = 1;
isNeedSave = false;
}
log += " 曝光值:" + std::to_string(exposures[x]) + "\r\n";
log += " 调整步长:" + std::to_string(*((int *)expStep + k)) + "\r\n";
}
memcpy((s == 0 ? &param.ExposureF[0] : &param.ExposureB[0]), exposures, sizeof(param.ExposureB));
}
printf("\n%s", log.c_str());
ftm_cr_log.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
if (isNeedSave)
{
log = "彩色明场校正完成\r\n";
if (m_captureCallback)
m_captureCallback(mode, log);
// log ="";
imwrite(param.Flat_WhitePath, mrgmat);
}
}
else
{
double values[2];
values[0] = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))).val[0];
values[1] = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))).val[0];
log = "-----开始灰色明场校正-----\r\n";
log += " 灰色扫描灰度明场均值:" + std::to_string(values[0]) + "," + std::to_string(values[1]) + "\r\n";
if (m_captureCallback)
m_captureCallback(mode, log);
for (int s = 0; s < 2; s++)
{
int *exposures = (int *)(s == 0 ? param.ExposureF : param.ExposureB);
int diff = LIGHT_DIFF(param.MaxBright, values[s]);
// if(abs(diff) > 30)
// radio = 2;
// else
// radio = 1;
double step = diff * radio;
log += " 明场:" + std::to_string(s) + ";diff" + std::to_string(diff) + "\r\n";
int preStep = expStep[s][0];
if (step * preStep < 0)
{
step = 0 - preStep / 2;
}
else
{
radio = 1;
}
if (step < 1 && step > 0)
step = 1;
if (step < 0 && step > -1)
step = -1;
int exp = *(exposures + 1);
// std::string ss1(string_format("exp[%d] = %d step = %.3f \r\n", s, exp, step));
// log += ss1;
bool isMinStep = abs(step) == 1 && step == expStep[s][0];
bool isOutBounds = exp >= (param.Sp / 3 / (mode ? 3 : 1) - 15) && step > 0;
isOutBounds |= exp <= 0 && step < 0;
if (isOutBounds)
log += "" + std::to_string(s) + "个明场校正异常 \r\n";
else if (abs(diff) > 1 || isMinStep)
{
exp += step;
if (exp < 0)
exp = 0;
if (exp > (param.Sp / 3 / (mode ? 3 : 1) - 15))
exp = param.Sp / 3 / (mode ? 3 : 1) - 15;
float coffe[3] = {1, 1, 1}; // 0.2, 1,0.51
for (int k = 0; k < 3; k++)
{
*(exposures + k) = (int)(exp * coffe[k]);
expStep[s][k] = (int)(step);
std::string exps(string_format("expStep[%d][%d] = %.3f\r\n", s, k, step));
log += exps;
std::string ss(string_format("exposures[%d] = %0.3f \r\n", k, exposures[k]));
log += ss;
}
isNeedSave = false;
}
}
printf("\n%s", log.c_str());
ftm_cr_log.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
if (isNeedSave)
{
printf("Save LUT image path :%s \n", param.Flat_WhitePath.c_str());
log = "灰度明场校正完成\r\n";
if (m_captureCallback)
m_captureCallback(mode, log);
log = "";
imwrite(param.Flat_WhitePath, mrgmat);
}
}
}
Get_Static_CorrectParam().SaveCorrectParam(param);
printf("exit Save_lut \n");
return isNeedSave;
}
void MultiFrameCapture_8478_HL::correctcolor(int correctmode)
{
printf(" correctcolor start mode = %d \n", correctmode);
auto _start = std::chrono::steady_clock::now();
std::map<int, std::pair<int, int>> mode = {{1, {1, 0}}, {2, {1, 1}}, {3, {2, 0}}, {4, {2, 1}}, {5, {3, 0}}, {6, {3, 1}}, {7, {16, 0}}, {8, {16, 1}},
{9, {17, 0}}, {10, {17, 1}},{11,{32,1}},{12,{32,0}},{13,{33,1}},{14,{33,0}}};
ThreadPool pool(2);
std::queue<std::future<void>> fu_correct;
std::string loginfo = "Start Correctcolor \r\n";
if (m_captureCallback)
m_captureCallback(0x01, loginfo);
if (correctmode != 0)
{
creatcorrectconfig(mode[correctmode].first, mode[correctmode].second);
auto param = Get_Static_CorrectParam().GetFpgaparam_8478(mode[correctmode].first, mode[correctmode].second);
fu_correct.emplace(pool.enqueue([param](int dpi, int color)
{ creatLUTData(dpi, color, param); },
mode[correctmode].first, mode[correctmode].second));
}
else
{
for (auto node : mode)
{
creatcorrectconfig(node.second.first, node.second.second);
auto param = Get_Static_CorrectParam().GetFpgaparam_8478(node.second.first, node.second.second);
fu_correct.emplace(pool.enqueue([param](int dpi, int color)
{ creatLUTData(dpi, color, param); },
node.second.first, node.second.second));
}
}
while (fu_correct.size())
{
fu_correct.front().get();
fu_correct.pop();
}
loginfo = "******Correct Done****** time " + std::to_string(std::chrono::duration<double>(std::chrono::steady_clock::now() - _start).count()) + "s";
if (m_captureCallback)
m_captureCallback(0x04, loginfo);
}
void MultiFrameCapture_8478_HL::fpga_reset()
{
reset_pin->setValue(Gpio::Low);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
reset_pin->setValue(Gpio::High);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
void MultiFrameCapture_8478_HL::fpga_reload()
{
// fpga 代码重载
fpgaLoad->setValue(Gpio::Low);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpga_conf_initn->setValue(Gpio::Low);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
printf("\n fpga_conf_done value %d", fpga_conf_done->getValue());
fpgaLoad->setValue(Gpio::High);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpga_conf_initn->setValue(Gpio::High);
// std::this_thread::sleep_for(std::chrono::milliseconds(5));
printf("\n fpga_conf_done value %d", fpga_conf_done->getValue());
// while(fpga_conf_done->getValue() == Gpio::GpioLevel::Low)
// std::this_thread::sleep_for(std::chrono::milliseconds(5));
std::this_thread::sleep_for(std::chrono::seconds(3));
printf("\n fpga_conf_done value %d", fpga_conf_done->getValue());
fpgaComm->resetADC();
fpgaComm->update(0);
}
void MultiFrameCapture_8478_HL::init_imagedatabuffer()
{
if (pimgdata_info.pdata)
free(pimgdata_info.pdata);
pimgdata_info.pdata = nullptr;
pimgdata_info.offset = pimgdata_info.frame_count = pimgdata_info.img_h = pimgdata_info.img_w = 0;
if (frame_count != 0)
{
int t_frame_count = fpgaComm->getFrameNum();
int width = this->width() * (m_config.g200params.color ? 3 : 1);
int height = frame_height * 2;
pimgdata_info.pdata = malloc(height * t_frame_count * width);
pimgdata_info.total = height * t_frame_count;
pimgdata_info.offset = 0;
pimgdata_info.frame_count = 0;
pimgdata_info.img_h = 0;
pimgdata_info.img_w = 0;
printf("pimgdata_info.pdata = %p malloc_size = %d \n", pimgdata_info.pdata, height * t_frame_count * width, t_frame_count, width, height);
}
}
void MultiFrameCapture_8478_HL::free_imagedatabuffer()
{
if (pimgdata_info.pdata)
free(pimgdata_info.pdata);
pimgdata_info.pdata = nullptr;
printf("--- free imagedatabuf --- \n");
}
// static void neon_memcpy(volatile void *dst, volatile void *src, int sz)
// {
// if (sz & 63)
// sz = (sz & -64) + 64;
// asm volatile (
// "NEONCopyPLD: \n"
// " VLDM %[src]!,{d0-d7} \n"
// " VSTM %[dst]!,{d0-d7} \n"
// " SUBS %[sz],%[sz],#0x40 \n"
// " BGT NEONCopyPLD \n"
// : [dst]"+r"(dst), [src]"+r"(src), [sz]"+r"(sz) : : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "cc", "memory");
// }
void MultiFrameCapture_8478_HL::update_imgdatainfo(void *itemmat, frame_data_info &info, uint32_t h, uint32_t w)
{
// StopWatch sw;
if (info.pdata && itemmat)
{
// neon_memcpy(pimgdata_info.pdata + pimgdata_info.offset,itemmat,h*w);
memcpy(info.pdata + info.offset, itemmat, h * w);
info.offset += h * w;
info.frame_count++;
info.img_h += h;
info.img_w = w;
// printf("offset = %d item_total = %d \n", pimgdata_info.offset,pimgdata_info.frame_count);
}
// printf("size = %d frame memcpy time = %fms \n", h*w,sw.elapsed_ms());
}
void MultiFrameCapture_8478_HL::update_imgdatainfo(void *itemmat, uint32_t h, uint32_t w)
{
if (pimgdata_info.pdata && itemmat)
{
memcpy(pimgdata_info.pdata + pimgdata_info.offset, itemmat, h * w);
pimgdata_info.offset += h * w;
pimgdata_info.frame_count++;
pimgdata_info.img_h += h;
pimgdata_info.img_w = w;
}
}
void MultiFrameCapture_8478_HL::init_adc_8478()
{
// std::this_thread::sleep_for(std::chrono::milliseconds(100));
for (int bank = 0; bank < 4; bank++)
for (int i = 1; i < 64; i++)
{
write_adc_8478(bank_change[bank], i, bank_value[i + 64 * bank], 1);
write_adc_8478(bank_change[bank], i, bank_value[i + 64 * bank], 0);
}
// std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
void MultiFrameCapture_8478_HL::write_adc_8478(int bank, int addr, int val, bool A_or_B)
{
uint32_t reg5 = 0;
fpgaComm->read(5, reg5);
fpgaComm->write(5, reg5 | 0xc000); // adc 配置使能打开
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
adc_8478_param p_adc{0};
p_adc.param.r_or_w_h = p_adc.param.r_or_w_l = 0;
p_adc.param.addr_l = 0;
p_adc.param.addr_h = addr;
p_adc.param.val_l = bank;
p_adc.param.val_h = val;
fpgaComm->write(A_or_B ? 4 : 7, p_adc.value);
uint32_t reg1_v;
fpgaComm->read(1, reg1_v);
Mode_FPGA reg1 = *((Mode_FPGA *)&reg1_v);
A_or_B ? reg1.adcA = 1 : reg1.adcB = 1;
fpgaComm->write(1, *((uint32_t *)&reg1));
A_or_B ? reg1.adcA = 0 : reg1.adcB = 0;
fpgaComm->write(1, *((uint32_t *)&reg1));
// std::this_thread::sleep_for(std::chrono::microseconds(100));
fpgaComm->write(5, reg5 & 0xffff3fff); // adc 配置使能关闭
}
uint32_t MultiFrameCapture_8478_HL::read_adc_8478(int bank, int addr, bool A_or_B)
{
uint32_t reg5 = 0;
fpgaComm->read(5, reg5);
fpgaComm->write(5, reg5 | 0xc000); // adc 配置使能打开
std::this_thread::sleep_for(std::chrono::milliseconds(1));
adc_8478_param p_adc{0};
p_adc.param.r_or_w_h = 0;
p_adc.param.r_or_w_l = 2;
p_adc.param.addr_l = 0;
p_adc.param.addr_h = addr;
p_adc.param.val_l = bank;
p_adc.param.val_h = 0;
fpgaComm->write(A_or_B ? 4 : 7, p_adc.value);
uint32_t reg1_v;
fpgaComm->read(1, reg1_v);
Mode_FPGA reg1 = *((Mode_FPGA *)&reg1_v);
A_or_B ? reg1.adcA = 1 : reg1.adcB = 1;
fpgaComm->write(1, *((uint32_t *)&reg1));
A_or_B ? reg1.adcA = 0 : reg1.adcB = 0;
fpgaComm->write(1, *((uint32_t *)&reg1));
std::this_thread::sleep_for(std::chrono::milliseconds(1));
fpgaComm->write(5, reg5 & 0xffff3fff); // adc 配置使能关闭
uint32_t read_reg = 0;
fpgaComm->read(3, read_reg);
return read_reg;
}
void MultiFrameCapture_8478_HL::set_exp_8478_single(int exp_r, int exp_g, int exp_b, int sp, bool A_or_B, bool is_gray)
{
int pix_counter = sp / 3 - 10;
// set_pixel_count_8478(pix_counter,is_gray);
int exp_max = pix_counter - 10;
if (exp_r > exp_max)
exp_r = exp_max;
if (exp_g > exp_max)
exp_g = exp_max;
if (exp_b > exp_max)
exp_b = exp_max;
write_adc_8478(bank_change[1], 0x7, 0, A_or_B); // exp R start
write_adc_8478(bank_change[1], 0x8, 0x35, A_or_B);
write_adc_8478(bank_change[1], 0x9, (exp_r & 0x7f00) / 0x100, A_or_B); // exp R end
write_adc_8478(bank_change[1], 0xa, exp_r & 0xff, A_or_B);
write_adc_8478(bank_change[1], 0xe, 0, A_or_B); // exp G start
write_adc_8478(bank_change[1], 0xf, 0x35, A_or_B);
write_adc_8478(bank_change[1], 0x10, (exp_g & 0x7f00) / 0x100, A_or_B); // exp G end
write_adc_8478(bank_change[1], 0x11, exp_g & 0xff, A_or_B);
write_adc_8478(bank_change[1], 0x15, 0, A_or_B); // exp B start
write_adc_8478(bank_change[1], 0x16, 0x35, A_or_B);
write_adc_8478(bank_change[1], 0x17, (exp_b & 0x7f00) / 0x100, A_or_B); // exp B end
write_adc_8478(bank_change[1], 0x18, exp_b & 0xff, A_or_B);
}
void MultiFrameCapture_8478_HL::set_led_off()
{
for (int i = 0; i < 2; i++)
{
write_adc_8478(bank_change[1], 0x7, 0, i); // exp R start
write_adc_8478(bank_change[1], 0x8, 0, i);
write_adc_8478(bank_change[1], 0x9, 0, i); // exp R end
write_adc_8478(bank_change[1], 0xa, 0, i);
write_adc_8478(bank_change[1], 0xe, 0, i); // exp G start
write_adc_8478(bank_change[1], 0xf, 0, i);
write_adc_8478(bank_change[1], 0x10, 0, i); // exp G end
write_adc_8478(bank_change[1], 0x11, 0, i);
write_adc_8478(bank_change[1], 0x15, 0, i); // exp B start
write_adc_8478(bank_change[1], 0x16, 0, i);
write_adc_8478(bank_change[1], 0x17, 0, i); // exp B end
write_adc_8478(bank_change[1], 0x18, 0, i);
}
}
void MultiFrameCapture_8478_HL::set_pixel_count_8478(int val, bool is_gray)
{
val = val - 10;
//fpgaComm->write(20, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
fpgaComm->write(19, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, true); // count0 -A
write_adc_8478(bank_change[1], 2, val & 0xff, true);
write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, false); // count0 -B
write_adc_8478(bank_change[1], 2, val & 0xff, false);
if (is_gray)
return;
write_adc_8478(bank_change[1], 3, (val & 0x7f00) / 0x100, true); // count1 -A
write_adc_8478(bank_change[1], 4, val & 0xff, true);
write_adc_8478(bank_change[1], 3, (val & 0x7f00) / 0x100, false); // count1 -B
write_adc_8478(bank_change[1], 4, val & 0xff, false);
write_adc_8478(bank_change[1], 5, (val & 0x7f00) / 0x100, true); // count2 -A
write_adc_8478(bank_change[1], 6, val & 0xff, true);
write_adc_8478(bank_change[1], 5, (val & 0x7f00) / 0x100, false); // count2 -B
write_adc_8478(bank_change[1], 6, val & 0xff, false);
}
void MultiFrameCapture_8478_HL::set_digital_offset_8478(int channel, int val, bool A_or_B, int color)
{
if (channel < 0 || channel > 8)
return;
if (color < 0 || color > 2)
return;
int s_addr = ((color == 0) ? 7 : ((color == 2) ? 1 : 0x1c));
int bank = color == 0 ? 0 : 3;
val = val & 0x1ff;
write_adc_8478(bank_change[bank], s_addr + channel * 2, val < 255 ? 1 : 0, A_or_B);
write_adc_8478(bank_change[bank], s_addr + 1 + channel * 2, val & 0xff, A_or_B);
}
void MultiFrameCapture_8478_HL::set_digital_gain_8478(int channel, uint8_t val, bool A_or_B, int color)
{
if (channel < 0 || channel > 8)
return;
if (color < 0 || color > 2)
return;
int s_addr = ((color == 0) ? 0x19 : ((color == 2) ? 0x13 : 0x2e));
int bank = color == 0 ? 0 : 3;
write_adc_8478(bank_change[bank], s_addr + channel, val, A_or_B);
}
void MultiFrameCapture_8478_HL::set_dpi_mode(int type)
{
write_adc_8478(bank_change[1], 0x38, 0x30, true);
write_adc_8478(bank_change[1], 0x38, 0x30, false);
int val = 0;
if(type == 1) val = 3;
if(type == 2) val = 0;
if(type == 3) val = 1;
write_adc_8478(bank_change[0], 0x33, val, true);
write_adc_8478(bank_change[0], 0x33, val, false);
}
void MultiFrameCapture_8478_HL::set_BOS_postion(uint32_t rise, uint32_t fall)
{
write_adc_8478(bank_change[2], 0x1, (rise & 0xff00) / 0x100, true); // A面 BOS 起始位置
write_adc_8478(bank_change[2], 0x2, rise & 0xff, true);
write_adc_8478(bank_change[2], 0x3, (fall & 0xff00) / 0x100, true); // A面 BOS 结束位置
write_adc_8478(bank_change[2], 0x4, fall & 0xff, true);
write_adc_8478(bank_change[2], 0x1, (rise & 0xff00) / 0x100, false); // B面 BOS 起始位置
write_adc_8478(bank_change[2], 0x2, rise & 0xff, false);
write_adc_8478(bank_change[2], 0x3, (fall & 0xff00) / 0x100, false); // B面 BOS 结束位置
write_adc_8478(bank_change[2], 0x4, fall & 0xff, false);
}
void MultiFrameCapture_8478_HL::set_EN_postion(uint32_t rise, uint32_t fall)
{
write_adc_8478(bank_change[2], 0xd, (rise & 0xff00) / 0x100, true); // A面 EN 起始位置
write_adc_8478(bank_change[2], 0xe, rise & 0xff, true);
write_adc_8478(bank_change[2], 0xf, (fall & 0xff00) / 0x100, true); // A面 EN 结束位置
write_adc_8478(bank_change[2], 0x10, fall & 0xff, true);
write_adc_8478(bank_change[2], 0xd, (rise & 0xff00) / 0x100, false); // B面 EN 起始位置
write_adc_8478(bank_change[2], 0xe, rise & 0xff, false);
write_adc_8478(bank_change[2], 0xf, (fall & 0xff00) / 0x100, false); // B面 EN 结束位置
write_adc_8478(bank_change[2], 0x10, fall & 0xff, false);
}
void MultiFrameCapture_8478_HL::set_7864A_current_ctrl(uint32_t current)
{
if (current > 6)
return;
write_adc_8478(bank_change[2], 0x1a, current * 0x10 + current, false);
write_adc_8478(bank_change[2], 0x1b, current * 0x10 + current, false);
write_adc_8478(bank_change[2], 0x1c, current * 0x10 + current, false);
write_adc_8478(bank_change[2], 0x1a, current * 0x10 + current, true);
write_adc_8478(bank_change[2], 0x1b, current * 0x10 + current, true);
write_adc_8478(bank_change[2], 0x1c, current * 0x10 + current, true);
}
void MultiFrameCapture_8478_HL::set_LED_PTN_8478(bool is_bw)
{
if (is_bw)
{
write_adc_8478(bank_change[0], 0x3d, 0x01, false);
write_adc_8478(bank_change[0], 0x3d, 0x01, true);
return;
}
write_adc_8478(bank_change[0], 0x3d, 0x11, false);
write_adc_8478(bank_change[0], 0x3d, 0x11, true);
}
void MultiFrameCapture_8478_HL::set_ADC_config_frequency(uint32_t freq)
{
uint32_t reg2 = 0;
fpgaComm->read(2, reg2);
fpgaComm->write(2, (reg2 & 0xffffffe1) | (freq << 1)); // adc 配置 频率
}
void MultiFrameCapture_8478_HL::set_cis_type_hl(bool is_hl)
{
uint32_t reg2 = 0;
fpgaComm->read(2, reg2);
fpgaComm->write(2, (reg2 & 0xffffffdf) | (is_hl ? 0x20: 0x0)); // 设置CIS类型 华菱
}
cv::Mat MultiFrameCapture_8478_HL::merge_8478(cv::Mat src, bool color, uint32_t version)
{
if (!color)
return src;
cv::Mat dst(src.rows, src.cols / 3, CV_8UC3);
uint32_t width = src.cols / 6;
cv::insertChannel(src(cv::Rect(0, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 0);
cv::insertChannel(src(cv::Rect(src.cols / 3, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 2);
cv::insertChannel(src(cv::Rect(src.cols / 3 * 2, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 1);
cv::insertChannel(src(cv::Rect(src.cols / 6, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 0);
cv::insertChannel(src(cv::Rect(src.cols / 6 * 3, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 2);
cv::insertChannel(src(cv::Rect(src.cols / 6 * 5, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 1);
return dst;
}
void MultiFrameCapture_8478_HL::single_correct(std::uint32_t mode)
{
std::vector<uint32_t> sup_correct_dpi{1, 2, 3, 0x10, 0x11,0x20,0x21};
union correct_mode_
{
struct
{
uint32_t dpi : 16;
uint32_t color_mode : 8;
uint32_t correct_mode : 8;
} param;
uint32_t value;
};
correct_mode_ tmp;
tmp.value = mode;
if (std::count(sup_correct_dpi.begin(), sup_correct_dpi.end(), tmp.param.dpi) && (tmp.param.color_mode < 2))
{
auto param = Get_Static_CorrectParam().GetFpgaparam_8478(tmp.param.dpi, tmp.param.color_mode);
if (tmp.param.correct_mode == 1)
creatLUTData(tmp.param.dpi, tmp.param.color_mode, param);
else if (tmp.param.correct_mode == 2)
creatLUTData_gray(tmp.param.dpi, tmp.param.color_mode, param);
}
}