#include  "rc_def.h"
#include  "comhead.h"
#pragma hdrstop

#include "m_motcom.h"
#include "m_mothw.h"
#include "m_layer.h"

HINSTANCE hModuleInstance;
static  char      mlVersion[] = "V 1.55 ("__DATE__")";

static  int       bModulLoaded = FALSE;
static BOOL    bReadyHit;
static  int     MoveFinishIdx;
static  int       nTimeTicks = 20;
static  int    nCallBackAction = 0;
static const    nScanSize = 150;
static  long    Scan[nScanSize+1];
extern HINSTANCE hGPIBModule;
static  UINT      nEvent;
static  UINT      nCycle = nScanSize;
static BOOL   bScanReady = TRUE;
static BOOL   bShowEncoder = FALSE;
char  buf[MaxString];
extern int    nC812;

LPMList lpMList = NULL;

#ifdef CHECK
long pos;
#pragma message ("Check")
#endif

LPCSTR  _export WINAPI mlGetVersion(void)
 {
 return (LPCSTR)mlVersion;
 };

HINSTANCE _export WINAPI mlGetInstance(void)
 {
 return hModuleInstance;
 };

//******************************************************************************
//***** Routines for optimizing the motors *************************************
//******************************************************************************
int _export WINAPI mGetScanSize(void)
 {
 return nScanSize;
 };

void _export WINAPI mStartMoveScan(int tic,int)
 {
 if(!bScanReady) return;
 nCycle = 0;
 memset(Scan,0,nScanSize);
 bReadyHit = FALSE;
 bScanReady = FALSE;
 nTimeTicks = tic;
 lpMList->MP()->StartCheckScan();
 };

void TC_812ISA::StartCheckScan(void)
 {
 // timeBeginPeriod(1);
 nCallBackAction = 1;
 nEvent = timeSetEvent(nTimeTicks,1,(LPTIMECALLBACK)mSavePosition,0,TIME_PERIODIC);
 MoveByPosition(wPositionWidth);
 };

void TC_812GPIB::StartCheckScan(void)
 {
 nCallBackAction = 1;
 MoveByPosition(wPositionWidth);
 nEvent = timeSetEvent(20,1,(LPTIMECALLBACK)mSavePosition,0,TIME_PERIODIC);
 };

void TC_832::StartCheckScan(void)
 {
 // timeBeginPeriod(1);
 nCallBackAction = 1;
 nEvent = timeSetEvent(nTimeTicks,1,(LPTIMECALLBACK)mSavePosition,0,TIME_PERIODIC);
 MoveByPosition(wPositionWidth);
 };

LPLONG _export WINAPI mGetMoveScan(void)
 {
 bScanReady = TRUE;
 return (LPLONG)Scan;
 };

int _export WINAPI mGetMoveFinishIdx(void)
 {
 return MoveFinishIdx;
 };

void _export CALLBACK mSavePosition(UINT nEvent,UINT,DWORD,DWORD,DWORD)
 {
 switch(nCallBackAction) {
  case 1:
  lpMList->MP()->GetPosition(FALSE);
  Scan[nCycle++] = lpMList->MP()->lPosition;
  if(!bReadyHit)
   if(lpMList->MP()->IsMoveFinish())
    {
    bReadyHit = TRUE;
    MoveFinishIdx = nCycle-1;
    }
  if(nCycle >= nScanSize)
   {
   timeKillEvent(nEvent);
   nCycle = 0;
   PostMessage(GetFrameHandle(),WM_COMMAND,cm_MoveScanReady,888l);
   }
  break;

  case 2:
  nCycle = 0;
  MoveFinishIdx = 1;
  PostMessage(GetFrameHandle(),WM_COMMAND,cm_MoveScanReady,888l);
  break;
  }
 };
//******************************************************************************
//******************************************************************************

//******************************************************************************
//***** C-Call interface for TMList ********************************************
//******************************************************************************
BOOL _export WINAPI mlInitializeMotorsDLL(void)
 {
 bModulLoaded = FALSE;
 bShowEncoder = GetPrivateProfileInt("Steuerprogramm","ArrangeMode",0,GetCFile());
 if(!lpMList->InitializeModule())
  return FALSE;
 bModulLoaded = TRUE;
 return TRUE;
 };

BOOL _export WINAPI mlSetAxis(int axis)
 {
 if(lpMList->SetAxis(axis))
  return TRUE;
 lpMList->SetAxis(0);
 return FALSE;
 };

int _export WINAPI mlGetAxis(void)
 {
 return lpMList->GetAxis();
 };

int _export WINAPI mlGetIdByName(TAxisType at)
 {
 int id = -1;

 switch(at) {
  case X:          id = lpMList->AD_X;       break;
  case Y:          id = lpMList->AD_Y;         break;
  case Z:          id = lpMList->AD_Z;       break;
  case Omega:      id = lpMList->AD_Omega;     break;
  case Theta:      id = lpMList->AD_Theta;     break;
  case Phi:        id = lpMList->AD_Phi;       break;
  case Psi:        id = lpMList->AD_Psi;       break;
  case Encoder:    id = lpMList->AD_Encoder;    break;
  case Monochromator: id = lpMList->AD_Monochromator; break;
  case Absorber:   id = lpMList->AD_Absorber;   break;
  case Collimator:  id = lpMList->AD_Collimator;  break;
  case DF:         id = lpMList->AD_DF;         break;
  case DC:         id = lpMList->AD_DC;         break;
  case Tilt:        id = lpMList->AD_Tilt;        break;
  case Rotation:    id = lpMList->AD_Rotation;     break;
  }
 return id;
 };

TAxisType _export WINAPI mlParsingAxis(LPSTR axisname)
 {
 return lpMList->ParsingAxis(axisname);
 };

BOOL _export WINAPI mlIsAxisValid(TAxisType type)
 {
 switch(type) {
  case X:          return (lpMList->AD_X > -1);
  case Y:          return (lpMList->AD_Y > -1);
  case Z:          return (lpMList->AD_Z > -1);
  case Omega:      return (lpMList->AD_Omega > -1);
  case Theta:      return (lpMList->AD_Theta > -1);
  case Phi:        return (lpMList->AD_Phi > -1);
  case Psi:        return (lpMList->AD_Psi > -1);
  case Encoder:    return (lpMList->AD_Encoder > -1);
  case Monochromator: return (lpMList->AD_Encoder > -1);
  case Absorber:   return (lpMList->AD_Absorber > -1);
  case Collimator:  return (lpMList->AD_Collimator > -1);
  case DF:         return (lpMList->AD_DF > -1);
  case DC:         return (lpMList->AD_DC > -1);
  case Tilt:       return (lpMList->AD_Tilt > -1);
  case Rotation:     return (lpMList->AD_Rotation > -1);
  default:    return FALSE;
  }
 };

BOOL _export WINAPI mlIsServerOK(void)
 {
 return bModulLoaded;
 };

int _export WINAPI mlGetAxisNumber(void)
 {
 return lpMList->GetAxisNumber();
 };

double _export WINAPI mlGetOffset(int mid)
 {
 return lpMList->MP(mid)->dAngleBias;
 };

void _export WINAPI mlSetAngleDefault(void)
 {
 lpMList->SetAngleDefault();
 };

void _export WINAPI mlOptimizingDlg(void)
 {
 PostMessage(GetFrameHandle(),WM_COMMAND,cm_CallExecuteScan,0l);
 lpMList->MP()->OptimizingDlg();
 };

BOOL _export WINAPI mlGetDistance(int mid,double& distance)
 {
 if(lpMList->MP(mid)->GetAngle(1))
  {
  distance = lpMList->MP(mid)->dAngle;
  return TRUE;
  }
 distance = 0.0;
 return FALSE;
 };

double _export WINAPI mlGetValue(int mid,TValueType vtype)
 {
 switch(vtype) {
  case Distance:   return lpMList->MP(mid)->dAngle;
  case MinDistance: return lpMList->MP(mid)->dAngleMin;
  case MaxDistance: return lpMList->MP(mid)->dAngleMax;
  case Speed:    return lpMList->MP(mid)->GetSpeed();
  case Width:    return lpMList->MP(mid)->GetAngleWidth();
  default:     return 1.0;
  }
 };

BOOL _export WINAPI mlMoveToDistance(int mid,double distance)
 {
 if(!bModulLoaded) return FALSE;
 lpMList->MP(mid)->MoveToAngle(distance);
 return TRUE;
 };

BOOL _export WINAPI mlIsMoveFinish(int mid)
 {
 return lpMList->MP(mid)->IsMoveFinish();
 };

void _export WINAPI mlSetParametersDlg(void)
 {
 lpMList->SetParametersDlg();
 };

void _export WINAPI mlPositionControlDlg(void)
 {
 lpMList->PositionControlDlg();
 };

void _export WINAPI mlSaveModuleSettings(void)
 {
 lpMList->SaveModuleSettings();
 };

void _export WINAPI mlInquireReferencePointDlg(int task)
 {
 lpMList->InquireReferencePointDlg(task);
 };

//******************************************************************************
//***** C-Call interface for TMotor ********************************************
//******************************************************************************
BOOL _export WINAPI mSetLine(int number,BOOL state)
 {
 if(!bModulLoaded) return FALSE;
 return lpMList->MP(nC812)->SetLine(number,state);
 };

void _export WINAPI mSetRelativeZero(BOOL yes,double value)
 {
 if(yes)
  lpMList->MP()->dAngleBias -= value;
  else
  lpMList->MP()->dAngleBias = 0.0;
 }

BOOL _export WINAPI mIsDistanceRelative(void)
 {
 return (lpMList->MP()->dAngleBias != 0.0);
 }

BOOL _export WINAPI mIsRangeHit(void)
 {
 return lpMList->MP()->IsRangeHit();
 };

BOOL _export WINAPI mMoveByDistance(double angle)
 {
 if(!bModulLoaded) return FALSE;
 lpMList->MP()->MoveByAngle(angle);
 return TRUE;
 };

BOOL _export WINAPI mMoveToDistance(double angle)
 {
 if(!bModulLoaded) return FALSE;
 lpMList->MP()->MoveToAngle(angle);
 return TRUE;
 };

BOOL _export WINAPI mIsMoveFinish(void)
 {
 if(!bModulLoaded) return TRUE;
 return lpMList->MP()->IsMoveFinish();
 };

BOOL _export WINAPI mGetDistance(double &ang)
 {
 if(lpMList->MP()->GetAngle(1))
  {
  ang = lpMList->MP()->dAngle;
  if(!bShowEncoder) return TRUE;
  sprintf(buf,"%ld",lpMList->MP()->lPosition);
  SetStatus(buf);
  return TRUE;
  }
 ang = 0.0;
 return FALSE;
 };

double _export WINAPI mGetDistanceProcess(void)
 {
 lpMList->MP()->GetAngle(0);
 return lpMList->MP()->dAngle;
 };

void _export WINAPI mStopDrive(BOOL restart)
 {
 lpMList->MP()->StopDrive(restart);
 };

double _export WINAPI mGetValue(TValueType vtype)
 {
 switch(vtype) {
  case Distance:   return lpMList->MP()->dAngle;
  case MinDistance: return lpMList->MP()->dAngleMin;
  case MaxDistance: return lpMList->MP()->dAngleMax;
  case Speed:    return lpMList->MP()->GetSpeed();
  case Width:    return lpMList->MP()->GetAngleWidth();
  default:     return 1.0;
  }
 };

BOOL _export WINAPI mSetValue(TValueType vtype,double value)
 {
 switch(vtype) {
  case Distance: case MinDistance: case MaxDistance:
  return FALSE;

  case Speed:
  return lpMList->MP()->SetSpeed(value);

  case Width:
  return lpMList->MP()->SetAngleWidth(value);
  }
 return FALSE;
 };

TUnitType _export WINAPI mGetUnitType(void)
 {
 return lpMList->MP()->eUnit;
 };

BOOL _export WINAPI mIsCalibrated(void)
 {
 return lpMList->MP()->IsCalibrated();
 };

void _export WINAPI mActivateDrive(void)
 {
 lpMList->MP()->ActivateDrive();
 };

void _export WINAPI mSetCorrectionState(BOOL onoff)
 {
 lpMList->MP()->SetCorrectionState(onoff);
 };

LPCSTR _export WINAPI mGetAxisName(void)
 {
 return lpMList->MP()->pCharacteristic();
 };

LPCSTR _export WINAPI mGetAxisUnit(void)
 {
 return (LPCSTR)lpMList->MP()->szUnit;
 };

LPCSTR _export WINAPI mGetSF(void)
 {
 return lpMList->MP()->pSF();
 };

LPCSTR _export WINAPI mGetDF(void)
 {
 return lpMList->MP()->pDF();
 };

int  _export WINAPI mExecuteCmd(LPSTR cmd)
 {
 return lpMList->MP()->ExecuteCmd(cmd);
 };

void  _export WINAPI mPushSettings(void)
 {
 lpMList->MP()->PushSettings();
 };

void  _export WINAPI mPopSettings(TMParameter mp)
 {
 lpMList->MP()->PopSettings(mp);
 };

//******************************************************************************
//******************************************************************************
#ifdef __WIN32__
#pragma message ("Win32")
TMFunctionTable MFT;

BOOL DllEntryPoint(HANDLE hModule,DWORD dwFunction,LPVOID)
 {
  if(!lpMList)
   lpMList = (LPMList)new TMList(10,NULL);
 switch (dwFunction)
  {
  case DLL_PROCESS_ATTACH:
  if(!lpMList)
   lpMList = (LPMList)new TMList(10,NULL);
  // Initialize function array.
  MFT.InitializeMotorsDLL = (TInitializeMotorsDLL)mlInitializeMotorsDLL;
  MFT.SetAxis             = (TSetAxis)            mlSetAxis;
  MFT.GetAxis             = (TGetAxis)            mlGetAxis;
  MFT.MoveToDistance      = (TMoveToDistance)     mMoveToDistance;
  MFT.MoveByDistance      = (TMoveByDistance)     mMoveByDistance;
  MFT.SetLine             = (TSetLine)            mSetLine;
  MFT.IsMoveFinish        = (TIsMoveFinish)       mIsMoveFinish;
  MFT.GetDistance         = (TGetDistance)        mGetDistance;
  MFT.IsServerOK          = (TIsServerOK)         mlIsServerOK;
  break;

  case DLL_PROCESS_DETACH:
  bModulLoaded = FALSE;
  if(hGPIBModule)
   FreeModule(hGPIBModule);
  break;
  };
 return TRUE;
 }
#else
int WINAPI LibMain(HINSTANCE inst,WORD,WORD,LPSTR)
 {
 bModulLoaded = FALSE;
 hModuleInstance = inst;
 lpMList = (LPMList)new TMList(10,inst);
 return -1;
 };

int CALLBACK WEP(int)
 {
 bModulLoaded = FALSE;
 if(hGPIBModule)
  FreeModule(hGPIBModule);
 return 1;
 };
#endif

// __LastLine__