#include <mil.h>
#include <milfpga.h>
#include <fpga_hist.h>
#define FUNCTION_NB_PARAM 3
#define FUNCTION_OPCODE_FPGA_HISTOGRAM 5
#define FUNCTION_PARAMETER_ERROR_CODE 1
#define FUNCTION_WRONG_FPGA_ERROR_CODE 2
void MFTYPE FPGAHistogram(MIL_ID Func);
void MFTYPE FPGAHistogramSlave(MIL_ID Func);
void FPGAHistogramPrimitive(MIL_ID Func, MIL_ID SrcImageId, MIL_ID HistBufId, MIL_INT ClearFlag);
void FPGAHistogramClearPrimitive(MIL_ID Func, MIL_ID SrcImageId, MIL_ID HistBufId);
void FPGAInitializeShadowRegisters(MIL_ID Func, MIL_FPGA_CONTEXT HistContext, FPGA_HIST_USER_ST* pHistShadow,
MIL_BUFFER_INFO Src, MIL_BUFFER_INFO Hist);
bool FindOffChipHistogram(MIL_ID MilSystem, MIL_FPGA_CONTEXT* pHistogram);
void FPGAHistogramPrimitive(MIL_ID Func, MIL_ID SrcImageId, MIL_ID HistBufId, MIL_INT ClearFlag)
{
MIL_BUFFER_INFO Src, Hist;
MIL_FPGA_CONTEXT HistogramContext;
FPGA_HIST_USER_ST HistShadow;
memset(&HistShadow, 0, sizeof(HistShadow));
if((ClearFlag == M_ENABLE) || (ClearFlag == M_DEFAULT))
FPGAHistogramClearPrimitive(Func, SrcImageId, HistBufId);
MfuncInquire(SrcImageId, M_BUFFER_INFO, &Src);
MfuncInquire(HistBufId, M_BUFFER_INFO, &Hist);
if(FindOffChipHistogram(MfuncBufOwnerSystemId(Src), &HistogramContext))
{
FPGAInitializeShadowRegisters(Func, HistogramContext, &HistShadow, Src, Hist);
MfpgaSetSource(HistogramContext, Src, M_INPUT0, M_DEFAULT);
MfpgaSetDestination(HistogramContext, Hist, M_OUTPUT0, M_DEFAULT);
MfpgaSetRegister(HistogramContext, M_USER, 0, sizeof(HistShadow),
(void*)(&HistShadow), M_WHEN_DISPATCHED);
MfpgaCommandQueue(HistogramContext, M_DEFAULT, M_DEFAULT);
MfpgaCommandFree(HistogramContext, M_DEFAULT);
}
else
{
MfuncErrorReport(
Func, M_FUNC_ERROR+FUNCTION_WRONG_FPGA_ERROR_CODE,
MIL_TEXT("This FPGA configuration does not support on-chip Histogram acceleration."),
MIL_TEXT("Please select the proper FPGA configuration file."),
MIL_TEXT("See the processing FPGA section of the milconfig utility."),
M_NULL
);
}
}
void FPGAHistogramClearPrimitive(MIL_ID Func, MIL_ID SrcImageId, MIL_ID HistBufId)
{
MIL_BUFFER_INFO Src, Hist;
MIL_FPGA_CONTEXT HistogramContext;
FPGA_HIST_USER_ST HistShadow;
memset(&HistShadow, 0, sizeof(HistShadow));
MfuncInquire(SrcImageId, M_BUFFER_INFO, &Src);
MfuncInquire(HistBufId, M_BUFFER_INFO, &Hist);
if(FindOffChipHistogram(MfuncBufOwnerSystemId(Src), &HistogramContext))
{
FPGAInitializeShadowRegisters(Func, HistogramContext, &HistShadow, Src, Hist);
HistShadow.ctrl.f.hoaclr = 1;
MfpgaSetSource(HistogramContext, Src, M_INPUT0, M_DEFAULT);
MfpgaSetDestination(HistogramContext, Hist, M_OUTPUT0, M_DEFAULT);
MfpgaSetRegister(HistogramContext, M_USER, 0, sizeof(HistShadow),
(void*)(&HistShadow), M_WHEN_DISPATCHED);
MfpgaCommandQueue(HistogramContext, M_DEFAULT, M_DEFAULT);
MfpgaCommandFree(HistogramContext, M_DEFAULT);
}
else
{
MfuncErrorReport(
Func, M_FUNC_ERROR+FUNCTION_WRONG_FPGA_ERROR_CODE,
MIL_TEXT("This FPGA configuration does not support on-chip Histogram acceleration."),
MIL_TEXT("Please select the proper FPGA configuration file."),
MIL_TEXT("See the processing FPGA section of the milconfig utility."),
M_NULL
);
}
}
void FPGAInitializeShadowRegisters(MIL_ID Func, MIL_FPGA_CONTEXT HistContext,
FPGA_HIST_USER_ST* pHistShadow, MIL_BUFFER_INFO Src, MIL_BUFFER_INFO Hist)
{
if(!(MfuncBufAttribute(Hist) & M_HIST_LIST))
{
MfuncErrorReport(
Func, M_FUNC_ERROR+FUNCTION_PARAMETER_ERROR_CODE,
MIL_TEXT("Destination buffer must be a M_HIST_LIST."),
M_NULL,
M_NULL,
M_NULL
);
}
if((MfuncBufSizeX(Hist)-1) < (MIL_INT)MfuncBufMaxValue(Src))
{
MfuncErrorReport(
Func, M_FUNC_ERROR+FUNCTION_PARAMETER_ERROR_CODE,
MIL_TEXT("Destiantion histogram buffer too small."),
M_NULL,
M_NULL,
M_NULL
);
}
if(MfuncBufSizeBand(Src) != 1)
{
MfuncErrorReport(
Func, M_FUNC_ERROR+FUNCTION_PARAMETER_ERROR_CODE,
MIL_TEXT("Only monochrome source buffers are supported for Histogram."),
M_NULL,
M_NULL,
M_NULL
);
}
switch(MfuncBufType(Src))
{
case 8+M_UNSIGNED:
case 8+M_SIGNED:
pHistShadow->ctrl.f.srctype = 0; break;
case 16+M_UNSIGNED:
case 16+M_SIGNED:
pHistShadow->ctrl.f.srctype = 1; break;
default:
MfuncErrorReport(
Func, M_FUNC_ERROR+FUNCTION_PARAMETER_ERROR_CODE,
MIL_TEXT("Only 8 and 16 bit source buffers are supported for Histogram."),
M_NULL,
M_NULL,
M_NULL
);
break;
}
switch((MIL_INT)MfuncBufMaxValue(Src))
{
case 0xFFFF:
pHistShadow->ctrl.f.drange = 0; break;
case 0x7FFF:
pHistShadow->ctrl.f.drange = 1; break;
case 0x3FFF:
pHistShadow->ctrl.f.drange = 2; break;
case 0x1FFF:
pHistShadow->ctrl.f.drange = 3; break;
case 0x0FFF:
pHistShadow->ctrl.f.drange = 4; break;
case 0x07FF:
pHistShadow->ctrl.f.drange = 5; break;
case 0x03FF:
pHistShadow->ctrl.f.drange = 6; break;
case 0x01FF:
pHistShadow->ctrl.f.drange = 7; break;
case 0x00FF:
pHistShadow->ctrl.f.drange = 8; break;
case 0x007F:
pHistShadow->ctrl.f.drange = 9; break;
case 0x003F:
pHistShadow->ctrl.f.drange = 10; break;
case 0x001F:
pHistShadow->ctrl.f.drange = 11; break;
case 0x000F:
pHistShadow->ctrl.f.drange = 12; break;
case 0x0007:
pHistShadow->ctrl.f.drange = 13; break;
case 0x0003:
pHistShadow->ctrl.f.drange = 14; break;
default:
MfuncErrorReport(
Func, M_FUNC_ERROR+FUNCTION_PARAMETER_ERROR_CODE,
MIL_TEXT("Source buffer data range must be between 4 and 65536."),
MIL_TEXT("It must also be a power of two."),
M_NULL,
M_NULL
);
break;
}
}
void FPGAHistogram(MIL_ID SrcImageId, MIL_ID HistBufId, MIL_INT ClearFlag)
{
MIL_ID Func;
MfuncAlloc(MIL_TEXT("FPGAHistogram"),
FUNCTION_NB_PARAM,
FPGAHistogramSlave, M_NULL, M_NULL,
M_USER_MODULE_1+FUNCTION_OPCODE_FPGA_HISTOGRAM,
M_DEFAULT,
&Func
);
MfuncParamMilId (Func, 1, SrcImageId, M_IMAGE, M_IN);
MfuncParamMilId (Func, 2, HistBufId, M_HIST_LIST, M_OUT);
MfuncParamMilInt(Func, 3, ClearFlag);
MfuncCall(Func);
MfuncFree(Func);
}
void MFTYPE FPGAHistogramSlave(MIL_ID Func)
{
MIL_ID SrcImageId, HistBufId;
MIL_INT ClearFlag;
MfuncParamValue(Func, 1, &SrcImageId);
MfuncParamValue(Func, 2, &HistBufId);
MfuncParamValue(Func, 3, &ClearFlag);
FPGAHistogramPrimitive(Func, SrcImageId, HistBufId, ClearFlag);
}
bool FindOffChipHistogram(MIL_ID MilSystem, MIL_FPGA_CONTEXT* pHistogram)
{
MIL_FPGA_CONTEXT HistogramContext = 0;
bool Done = false;
MIL_INT InstanceNbr = M_DEV0, Capability;
do
{
if(MfpgaCommandAlloc(MilSystem, M_DEV0, FPGA_HIST_FID,
M_DEFAULT, InstanceNbr++, M_SYNCHRONOUS, M_DEFAULT, &HistogramContext))
{
MfpgaCommandInquire(HistogramContext, M_CAPABILITY, &Capability);
if((Capability & FPGA_HIST_CPBLTY_EXTERNAL_SRAM_SUPPORT) == 0)
{
Done = true;
}
else
{
MfpgaCommandFree(HistogramContext, M_DEFAULT);
HistogramContext = 0;
}
}
else
Done = true;
}
while(!Done);
*pHistogram = HistogramContext;
return ((*pHistogram) != 0);
}