/*************************************************************************/
/*
 * File name: FdkMinMaxMain.cpp
 * Location:  ...\Matrox Imaging\MILxxx\Examples\BoardSpecific\solios\C++\SoliosFDK
 *             \MinMaxPrimitive
 *
 * Synopsis:  This example shows how to test and benchmark a custom FPGA
 *            accelerated processing function that performs a Min and Max 
 *            operation on a source image. 
 */

/* Headers. */
#include <mil.h>

#define NB_LOOP            100
#define IMAGE_FILE         M_IMAGE_PATH MIL_TEXT("Board.mim")

/* Master MIL functions declaration. */
void FPGAMinMax(MIL_ID SrcImageId, MIL_UINT32* pMinValue, MIL_UINT32* pMaxValue);

/* Main test and benchmark function. */
/* --------------------------------- */

int MosMain(void)
   {
   MIL_ID   MilApplication;
   MIL_ID   MilSystem     ;
   MIL_ID   MilDisplay    ;
   MIL_ID   MilImageSrc   ;
   MIL_ID   MilImageDisp  ;
   MIL_INT  SizeX, SizeY, BoardType, n;
   MIL_UINT32 MinValue, MaxValue;
   MIL_DOUBLE Time;

   /* Allocate defaults. */
   MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL);

   /* Check if the processing FPGA is present. */
   MsysInquire(MilSystem, M_BOARD_TYPE, &BoardType);
   if(!(BoardType & M_PF))
      {
      MosPrintf(MIL_TEXT("Error, this example needs a processing FPGA installed on your\n"));
      MosPrintf(MIL_TEXT("board to continue.\n"));
      MosPrintf(MIL_TEXT("Press <Enter> to quit.\n"));
      MosGetch();
      MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL);    
      return 0;
      }

   /* Allocate buffers and initialize them. */
   /* For FPGA acceleration, all source buffers must be in FPGA accessible memory. */
   SizeX = MbufDiskInquire(IMAGE_FILE, M_SIZE_X, M_NULL);
   SizeY = MbufDiskInquire(IMAGE_FILE, M_SIZE_Y, M_NULL);
   MbufAlloc2d(MilSystem,
               SizeX,
               SizeY,
               8+M_UNSIGNED,
               M_IMAGE+M_PROC+M_GRAB+M_FPGA_ACCESSIBLE,
               &MilImageSrc);
   MbufLoad(IMAGE_FILE, MilImageSrc);

   /* Allocate a display buffer to show the image being processed. */
   MbufAlloc2d(MilSystem,
               SizeX,
               SizeY,
               8+M_UNSIGNED,
               M_IMAGE+M_DISP,
               &MilImageDisp);
   MbufLoad(IMAGE_FILE, MilImageDisp);
   MdispSelect(MilDisplay, MilImageDisp);

   MosPrintf(MIL_TEXT("This example demonstrates how to use the Mfpga API to program\n"));
   MosPrintf(MIL_TEXT("a MinMax primitive. Press <Enter> to continue.\n"));
   MosGetchar();
   
   /* Do a first iteration to load the Mfpga library. */
   FPGAMinMax(MilImageSrc, &MinValue, &MaxValue);

   MappTimer(M_DEFAULT, M_TIMER_RESET+M_SYNCHRONOUS, M_NULL);
   for(n = 0; n < NB_LOOP; n++)
      {
      /* Min = Min(SrcImage), Max = Max(SrcImage)  */
      FPGAMinMax(MilImageSrc, &MinValue, &MaxValue);
      }
   MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &Time);

   MosPrintf(MIL_TEXT("MinValue: %d\n"), MinValue);
   MosPrintf(MIL_TEXT("MaxValue: %d\n"), MaxValue);
   MosPrintf(MIL_TEXT("MinMax time: %.3f ms.\n"), (Time*1000)/NB_LOOP);
   MosPrintf(MIL_TEXT("Press a key to terminate.\n\n"));
   MosGetchar();

   /* Free MIl objects. */
   MbufFree(MilImageSrc);
   MbufFree(MilImageDisp);
   MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL);

   return 0;
   }