using Aurora.Api;
using Hermes;
using System;
using System.Runtime.InteropServices;
namespace AuroraLaserScanner
{
class ScannerRTC5 : ScannerObj
{
static new readonly Logger Log = new Logger("Scanner");
// For storage of each queried data set, the user program must provide (at an address specified by Ptr) an area of PC main memory equal to 528520 bytes.
[MarshalAs(UnmanagedType.LPArray, SizeConst = 528520)] uint[] m_coordinationTransformPtr = new uint[528520];
//set_trigger 관련 추가, get_waveform 에서 얻어올 포인터 추가, 최대 크기로 설정 (2^20 = 1,048,576)
[MarshalAs(UnmanagedType.LPArray, SizeConst = 1048576)] int[] m_getWaveformPtr = new int[1048576];
static uint MEM1 = 1048576; // 2^20;
static uint MEM2 = 0; // 2^20;
private bool _ModulationMode = false;
public override uint Open()
{
uint errorCode = NO_ERROR;
try {
errorCode = RTC5Wrap.init_rtc5_dll();
if (!IsOpenUnit && errorCode != 0U && errorCode != 2U) {
RTC5Wrap.free_rtc5_dll();
throw new Exception(string.Format("ERR_SCANNER_FAIL_TO_OPEN_DLL_FILE;ERROR CODE:{0}", errorCode));
}
IsOpenUnit = true;
} catch (Exception ex) {
throw ex;
}
return errorCode;
}
public override void Close()
{
if (IsOpenUnit == true) {
RTC5Wrap.free_rtc5_dll();
IsOpenUnit = false;
}
}
public override int Initialize(ScannerConfig config)
{
//작성 필요
uint errorCode = NO_ERROR;
var res = base.Initialize(config);
if (res != E1.OK) {
return res;
}
_ModulationMode = config.Modulation;
RTC5Wrap.n_stop_execution(m_deviceNo);
Log.D(string.Format("[RTC5ScannerUnit] 스캐너 실행 강제 정지"));
errorCode = LoadProgramFile(config.ProgramFile);
if (errorCode != NO_ERROR) {
Log.E(string.Format($"ERR_SCANNER_FAIL_TO_LOAD_PROGRAM_FILE;ERROR CODE:{errorCode},FILE:{config.ProgramFile}"));
return E1.ARGUMENT;
}
Log.D(string.Format($"[RTC5ScannerUnit] Program 파일({config.ProgramFile}) 로딩"));
errorCode = LoadCorrectionFile(config.CorrectionFile, 1, config.Use3DMode);
if (errorCode != NO_ERROR) {
Log.E(string.Format($"ERR_SCANNER_FAIL_TO_LOAD_CORRECTION_FILE;ERROR CODE:{errorCode},FILE:{config.CorrectionFile}"));
return E1.ARGUMENT;
}
Log.D(string.Format($"[RTC5ScannerUnit] Correction 파일({config.CorrectionFile}) 로딩"));
errorCode = LoadCorrectionFile(config.LaserCorrectionFile, 2, config.Use3DMode);
if (errorCode != NO_ERROR) {
Log.E(string.Format($"ERR_SCANNER_FAIL_TO_LOAD_CORRECTION_FILE;ERROR CODE:{errorCode},FILE:{config.LaserCorrectionFile}"));
return E1.ARGUMENT;
}
Log.D(string.Format($"[RTC5ScannerUnit] Correction 파일({config.LaserCorrectionFile}) 로딩"));
//수정
SelectCorrectionTable(1);
Log.D(string.Format("[RTC5ScannerUnit] Correction Table 설정"));
SetControlMode(config.ControlMode);
Log.D(string.Format($"[RTC5ScannerUnit] Control 모드 설정(Value:{config.ControlMode})"));
SetLaserMode(config.LaserMode);
Log.D(string.Format($"[RTC5ScannerUnit] Laser 모드 설정(Value:{config.LaserMode})"));
SetLaserControl(config.LaserControl);
Log.D(string.Format($"[RTC5ScannerUnit] Laser 컨트롤값 설정(Value:{config.LaserControl})"));
SetFirstPulseKiller(config.FirstPulseKiller);
Log.D(string.Format($"[RTC5ScannerUnit] Firse Killer값 설정(Value:{config.FirstPulseKiller})"));
ConfigLaserSignal(config.LaserSiganlPin2, config.LaserSiganlPin1, config.LaserSiganlPin9);
Log.D(string.Format($"[RTC5ScannerUnit] Laser Signal Pin (Value:{config.LaserSiganlPin2},{config.LaserSiganlPin1},{config.LaserSiganlPin9})"));
SetEthernetConfigLinkLoss(config.EthernetConfigLinkLoss);
Log.D(string.Format($"[RTC5ScannerUnit] Ehternet 연결 끊김 설정(Value:{config.EthernetConfigLinkLoss})"));
for (uint i = 0; i < PORT_COUNT; i++) {
RTC5Wrap.n_set_port_default(m_deviceNo, i, 0);
Log.D(string.Format($"[RTC5ScannerUnit] {i + 1}번 Port 값 초기화"));
}
SetConfigList(config.memory1, config.memory2);
Log.D(string.Format($"[RTC5ScannerUnit] ConfigList Portion값 설정(Memory1:{config.memory1} / Memory2:{config.memory2})"));
var item = GetListSpace();
#region ExecuteUpdateParameterList();
SetStartList(eListNo.LIST1);
SetScannerDelay(config.JumpDelay, config.MarkDelay, config.PolygonDelay);
Log.D(string.Format($"[RTC5ScannerUnit] 스캐너 Delay값 설정(Jump:{config.JumpDelay},Mark:{config.MarkDelay},Polygon:{config.PolygonDelay})"));
SetLaesrDelay(config.LaserOnDelay, config.LaserOffDelay);
Log.D(string.Format($"[RTC5ScannerUnit] 레이저 Delay값 설정(On:{config.LaserOnDelay},Off:{config.LaserOffDelay})"));
SetLaserTiming(config.LaserPeriod, config.Laser1PulseWidth, config.Laser1PulseWidth);
Log.D(string.Format($"[RTC5ScannerUnit] 레이저 Timing값 설정(Period:{config.LaserPeriod},Laser1PulseWidth:{config.Laser1PulseWidth})"));
SetJumpSpeed(config.JumpSpeed);
SetMarkSpeed(config.MarkSpeed);
Log.D(string.Format($"[RTC5ScannerUnit] 스캐너 속도값 설정(Jump:{config.JumpSpeed},Mark:{config.MarkSpeed})"));
SetEndList();
ExecuteList(eListNo.LIST1);
while (GetBusyStatus() == true) ;
#endregion
#region 2.스캐너모터 원점 복귀
CommandPosX = 0;
CommandPosY = 0;
CommandPosZ = 0;
if (config.Use3DMode) {
RTC5Wrap.n_home_position_xyz(m_deviceNo, (int)CommandPosX, (int)CommandPosY, (int)CommandPosZ);
Log.D(string.Format($"[RTC5ScannerUnit] 스캐너 X,Y,Z축 위치값 원점복귀"));
} else {
RTC5Wrap.n_home_position(m_deviceNo, (int)CommandPosX, (int)CommandPosY);
Log.D(string.Format($"[RTC5ScannerUnit] 스캐너 X,Y,Z축 위치값 원점복귀"));
}
#endregion
// Rotary On The Fly 임시
if (config.UseMarkingOnTheFly && config.OnTheFlyCoordinate == eOntheFlyCoordinate.Rotate) {
SetRotateCenter(config.MarkingOnTheFlyRotateCenterX, config.MarkingOnTheFlyRotateCenterY);
}
#region 좌표 변환 작업 수행
SetOffset(config.TranslationXOffset, config.TranslationYOffset, 1);
SetAngle(config.TranslationAngle, 1);
Log.D(string.Format($"[RTC5ScannerUnit] 스캐너 좌표 변화값 설정(X,Y,Θ:{config.TranslationXOffset},{config.TranslationYOffset},{config.TranslationAngle})"));
#endregion
#region 3.RTC보드의 transform data를 PC로 옮기는 기능 수행
while (GetBusyStatus() == true) ;
errorCode = RTC5Wrap.n_upload_transform(m_deviceNo, config.PrimaryHeadNo, m_coordinationTransformPtr);
if (errorCode != NO_ERROR) {
throw new Exception(string.Format("ERR_SCANNER_FAIL_TO_UPLOAD_TRANSFORM;ERROR CODE:{0}", errorCode));
}
Log.D(string.Format($"[RTC5ScannerUnit] Upload Transformation 작업 완료"));
#endregion
return E1.OK;
}
public override bool GetModulationMode()
{
return _ModulationMode;
}
public override void JumpAbs(double x, double y, eFunctionType type = eFunctionType.COMMAND)
{
CommandPosX = x;
CommandPosY = y;
int nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
int nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
if (type == eFunctionType.COMMAND) {
RTC5Wrap.n_goto_xy(m_deviceNo, nX, nY);
} else {
RTC5Wrap.n_jump_abs(m_deviceNo, nX, nY);
}
}
public override void JumpAbs3D(double x, double y, double z, eFunctionType type = eFunctionType.COMMAND)
{
CommandPosX = x;
CommandPosY = y;
CommandPosZ = z;
int nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
int nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
int nZ = Convert.ToInt32(CommandPosZ * m_ScaleZFactor);
if (type == eFunctionType.COMMAND) {
RTC5Wrap.n_goto_xyz(m_deviceNo, nX, nY, nZ);
} else {
RTC5Wrap.n_jump_abs_3d(m_deviceNo, nX, nY, nZ);
}
}
public override void JumpRel(double x, double y, eFunctionType type = eFunctionType.COMMAND)
{
CommandPosX += x;
CommandPosY += y;
int nX, nY;
if (type == eFunctionType.COMMAND) {
nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
RTC5Wrap.n_goto_xy(m_deviceNo, nX, nY);
} else {
nX = Convert.ToInt32(x * m_ScaleXYFactor);
nY = Convert.ToInt32(y * m_ScaleXYFactor);
RTC5Wrap.n_jump_rel(m_deviceNo, nX, nY);
}
}
public override void JumpRel3D(double x, double y, double z, eFunctionType type = eFunctionType.COMMAND)
{
CommandPosX += x;
CommandPosY += y;
CommandPosZ += z;
int nX, nY, nZ;
if (type == eFunctionType.COMMAND) {
nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
nZ = Convert.ToInt32(CommandPosZ * m_ScaleZFactor);
RTC5Wrap.n_goto_xyz(m_deviceNo, nX, nY, nY);
} else {
nX = Convert.ToInt32(x * m_ScaleXYFactor);
nY = Convert.ToInt32(y * m_ScaleXYFactor);
nZ = Convert.ToInt32(z * m_ScaleZFactor);
RTC5Wrap.n_jump_rel_3d(m_deviceNo, nX, nY, nZ);
}
}
public override void MarkAbs(double x, double y)
{
CommandPosX = x;
CommandPosY = y;
int nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
int nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
RTC5Wrap.n_mark_abs(m_deviceNo, nX, nY);
}
public override void MarkRel(double x, double y)
{
CommandPosX += x;
CommandPosY += y;
int nX = Convert.ToInt32(x * m_ScaleXYFactor);
int nY = Convert.ToInt32(y * m_ScaleXYFactor);
RTC5Wrap.n_mark_rel(m_deviceNo, nX, nY);
}
public override void ArcAbs(double x, double y, double angle)
{
CommandPosX = x;
CommandPosY = y;
int nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
int nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
//각도는 시계방향이 플러스
RTC5Wrap.n_arc_abs(m_deviceNo, nX, nY, angle * (-1));
}
public override void ArcRel(double x, double y, double angle)
{
CommandPosX += x;
CommandPosY += y;
int nX = Convert.ToInt32(x * m_ScaleXYFactor);
int nY = Convert.ToInt32(y * m_ScaleXYFactor);
//각도는 시계방향이 플러스
RTC5Wrap.n_arc_abs(m_deviceNo, nX, nY, angle * (-1));
}
public override void JumpAbsZ(double z, eFunctionType type = eFunctionType.COMMAND)
{
CommandPosZ = z;
int nZ = Convert.ToInt32(CommandPosZ * m_ScaleZFactor);
if (type == eFunctionType.COMMAND) {
RTC5Wrap.n_set_defocus(m_deviceNo, nZ);
} else {
RTC5Wrap.n_set_defocus_list(m_deviceNo, nZ);
}
}
public override void JumpRelZ(double z, eFunctionType type = eFunctionType.COMMAND)
{
CommandPosZ += z;
int nZ = Convert.ToInt32(CommandPosZ * m_ScaleZFactor);
if (type == eFunctionType.COMMAND) {
RTC5Wrap.n_set_defocus(m_deviceNo, nZ);
} else {
RTC5Wrap.n_set_defocus_list(m_deviceNo, nZ);
}
}
public override void GetXYPos(out double x, out double y)
{
if (m_UseEncoderFeedbackMode == true) {
RTC5Wrap.n_control_command(m_deviceNo, m_PrimaryHeadNo, 1, 0x501);
int currXPos = RTC5Wrap.n_get_value(m_deviceNo, 1);
//int currXPos = RTC5Wrap.n_get_value(m_deviceNo, 7);
RTC5Wrap.n_control_command(m_deviceNo, m_PrimaryHeadNo, 2, 0x501);
int currYPos = RTC5Wrap.n_get_value(m_deviceNo, 2);
//int currYPos = RTC5Wrap.n_get_value(m_deviceNo, 8);
// RTC보드의 각종 correction파일의 정보를 PC 메모리로 옮겨놓은 데이터로 변경함
uint error = RTC5Wrap.transform(out currXPos, out currYPos, m_coordinationTransformPtr, 0);
x = currXPos / m_ScaleXYFactor;
y = currYPos / m_ScaleXYFactor;
} else {
x = CommandPosX;
y = CommandPosY;
}
}
public override void GetZPos(out double z)
{
if (m_UseEncoderFeedbackMode == true) {
RTC5Wrap.n_control_command(m_deviceNo, 2, 1, 0x501);
int[] currZPos = new int[2];
currZPos[0] = RTC5Wrap.n_get_value(m_deviceNo, 4);
currZPos[1] = 0;//Unuse Axis
RTC5Wrap.transform(out currZPos[0], out currZPos[1], m_coordinationTransformPtr, 1);
z = (currZPos[0] / 16) / m_ScaleZFactor;//get_value로 얻은 bit 값([–524288 … 524287]) 을 z축 bit 값([-32768...32767])로 변환하기 위해 16으로 나누어 줌
} else {
z = CommandPosZ;
}
}
public override void WriteDA(uint portNo, float value/*0~100%*/, eFunctionType type = eFunctionType.COMMAND)
{
uint targetValue = (uint)(value * 40.95); // 인수 범위는 0 ~ 4095
if (type == eFunctionType.COMMAND) {
RTC5Wrap.n_write_da_x(m_deviceNo, portNo, targetValue);
} else {
RTC5Wrap.n_write_da_x_list(m_deviceNo, portNo, targetValue);
}
}
public override void GetEncoder(out double encoderX, out double encoderY, bool rotateMode = false)
{
int valueX, valueY;
RTC5Wrap.n_get_encoder(m_deviceNo, out valueX, out valueY);
if (m_MarkingOnTheFlyEncoderResolutionX != 0)
encoderX = (valueX / 1000f) * m_MarkingOnTheFlyEncoderResolutionX; // 단위는 count
else
encoderX = 0;
if (m_MarkingOnTheFlyEncoderResolutionY != 0)
encoderY = (valueY / 1000f) * m_MarkingOnTheFlyEncoderResolutionY; // 단위는 count
else
encoderY = 0;
if (rotateMode) {
if (m_MarkingOnTheFlyEncoderResolutionRotate != 0) {
encoderX = (valueX * 360f) / m_MarkingOnTheFlyEncoderResolutionRotate; // 단위는 count
encoderY = (valueY * 360f) / m_MarkingOnTheFlyEncoderResolutionRotate;
} else {
encoderX = 0; encoderY = 0;
}
}
}
public override uint GetMarkingInfo()
{
return RTC5Wrap.n_get_marking_info(m_deviceNo);
}
public override uint GetStartStopInfo()
{
return RTC5Wrap.n_get_startstop_info(m_deviceNo);
}
public override void StoreEncoder(uint pos)
{
RTC5Wrap.n_store_encoder(m_deviceNo, pos);
}
public override void ReadEncoder(out double encoder0_0, out double encoder1_0, out double encoder0_1, out double encoder1_1, bool rotateMode = false)
{
int buffEncoder0_0, buffEncoder1_0, buffEncoder0_1, buffEncoder1_1;
RTC5Wrap.n_read_encoder(m_deviceNo, out buffEncoder0_0, out buffEncoder1_0, out buffEncoder0_1, out buffEncoder1_1);
if (m_MarkingOnTheFlyEncoderResolutionX != 0) {
encoder0_0 = (buffEncoder0_0 / 1000f) * m_MarkingOnTheFlyEncoderResolutionX; // 단위는 count
encoder0_1 = (buffEncoder0_1 / 1000f) * m_MarkingOnTheFlyEncoderResolutionX; // 단위는 count
} else {
encoder0_0 = 0;
encoder0_1 = 0;
}
if (m_MarkingOnTheFlyEncoderResolutionY != 0) {
encoder1_0 = (buffEncoder1_0 / 1000f) * m_MarkingOnTheFlyEncoderResolutionX; // 단위는 count
encoder1_1 = (buffEncoder1_1 / 1000f) * m_MarkingOnTheFlyEncoderResolutionX; // 단위는 count
} else {
encoder1_0 = 0;
encoder1_1 = 0;
}
if (rotateMode) {
encoder0_0 = (buffEncoder0_0 * 360f) / m_MarkingOnTheFlyEncoderResolutionRotate;
encoder1_0 = (buffEncoder1_0 * 360f) / m_MarkingOnTheFlyEncoderResolutionRotate;
encoder0_1 = (buffEncoder0_1 * 360f) / m_MarkingOnTheFlyEncoderResolutionRotate;
encoder1_1 = (buffEncoder1_1 * 360f) / m_MarkingOnTheFlyEncoderResolutionRotate;
}
}
public override void WaitForEncoderX(double position)
{
if (m_MarkingOnTheFlyEncoderResolutionX == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((position * 1000) / m_MarkingOnTheFlyEncoderResolutionX); // 단위는 count
RTC5Wrap.n_wait_for_encoder(m_deviceNo, value, 0);
}
public override void WaitForEncoderY(double position)
{
if (m_MarkingOnTheFlyEncoderResolutionY == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((position * 1000) / m_MarkingOnTheFlyEncoderResolutionY); // 단위는 count
RTC5Wrap.n_wait_for_encoder(m_deviceNo, value, 1);
}
public override void WaitForEncoderRotateX(double angle)
{
if (m_MarkingOnTheFlyEncoderResolutionRotate == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((angle) / 360 * m_MarkingOnTheFlyEncoderResolutionRotate); // 단위는 count
RTC5Wrap.n_wait_for_encoder(m_deviceNo, value, 0);
}
public override void WaitForEncoderRotateY(double angle)
{
if (m_MarkingOnTheFlyEncoderResolutionRotate == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((angle) / 360 * m_MarkingOnTheFlyEncoderResolutionRotate); // 단위는 count
RTC5Wrap.n_wait_for_encoder(m_deviceNo, value, 1);
}
public override void WaitForEncoderRotateXMode(double angle, eEncoderWaitThroughMode mode)
{
if (m_MarkingOnTheFlyEncoderResolutionRotate == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((angle) / 360 * m_MarkingOnTheFlyEncoderResolutionRotate); // 단위는 count
RTC5Wrap.n_wait_for_encoder_mode(m_deviceNo, value, 0, (int)mode);
}
public override void WaitForEncoderRotateYMode(double angle, eEncoderWaitThroughMode mode)
{
if (m_MarkingOnTheFlyEncoderResolutionRotate == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((angle) / 360 * m_MarkingOnTheFlyEncoderResolutionRotate); // 단위는 count
RTC5Wrap.n_wait_for_encoder_mode(m_deviceNo, value, 1, (int)mode);
}
public override void WaitForEncoderXMode(double position, eEncoderWaitThroughMode mode)
{
double resolution = 0;
resolution = m_MarkingOnTheFlyEncoderResolutionX;
if (resolution == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((position * 1000) / resolution); // 단위는 count
RTC5Wrap.n_wait_for_encoder_mode(m_deviceNo, value, 0, (int)mode);
}
public override void WaitForEncoderYMode(double position, eEncoderWaitThroughMode mode)
{
double resolution = 0;
resolution = m_MarkingOnTheFlyEncoderResolutionY;
if (resolution == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((position * 1000) / resolution); // 단위는 count
RTC5Wrap.n_wait_for_encoder_mode(m_deviceNo, value, 1, (int)mode);
}
public override void WaitForEncoderMode(double position, uint encoderNo, eEncoderWaitThroughMode mode)
{
double resolution = 0;
if (encoderNo == 0) {
resolution = m_MarkingOnTheFlyEncoderResolutionX;
} else if (encoderNo == 1) {
resolution = m_MarkingOnTheFlyEncoderResolutionY;
} else {
throw new Exception("Encoder Number is incorrect");
}
if (resolution == 0) {
throw new DivideByZeroException("Encoder resolution value is 0");
}
int value = Convert.ToInt32((position * 1000) / resolution); // 단위는 count
RTC5Wrap.n_wait_for_encoder_mode(m_deviceNo, value, encoderNo, (int)mode);
}
public override void WaitForEncoderRange(double minX, double maxX, double minY, double maxY)
{
int valueMinX = Convert.ToInt32((minX * 1000) / m_MarkingOnTheFlyEncoderResolutionX); // 단위는 count
int valueMaxX = Convert.ToInt32((maxX * 1000) / m_MarkingOnTheFlyEncoderResolutionX); // 단위는 count
int valueMinY = Convert.ToInt32((minY * 1000) / m_MarkingOnTheFlyEncoderResolutionY); // 단위는 count
int valueMaxY = Convert.ToInt32((maxY * 1000) / m_MarkingOnTheFlyEncoderResolutionY); // 단위는 count
valueMinX = CutValue(valueMinX, (-1) * (int)Math.Pow(2, 31), (int)Math.Pow(2, 31) - 1);
valueMaxX = CutValue(valueMaxX, (-1) * (int)Math.Pow(2, 31), (int)Math.Pow(2, 31) - 1);
valueMinY = CutValue(valueMinY, (-1) * (int)Math.Pow(2, 31), (int)Math.Pow(2, 31) - 1);
valueMaxY = CutValue(valueMaxY, (-1) * (int)Math.Pow(2, 31), (int)Math.Pow(2, 31) - 1);
RTC5Wrap.n_wait_for_encoder_in_range(m_deviceNo, valueMinX, valueMaxX, valueMinY, valueMaxY);
}
public override void WaitForEncoderRotateRange(double minX, double maxX, double minY, double maxY)
{
int valueMinX = Convert.ToInt32((minX) / 360 * m_MarkingOnTheFlyEncoderResolutionRotate); // 단위는 count
int valueMaxX = Convert.ToInt32((maxX) / 360 * m_MarkingOnTheFlyEncoderResolutionRotate); // 단위는 count
int valueMinY = Convert.ToInt32((minY) / 360 * m_MarkingOnTheFlyEncoderResolutionRotate); // 단위는 count
int valueMaxY = Convert.ToInt32((maxY) / 360 * m_MarkingOnTheFlyEncoderResolutionRotate); // 단위는 count
valueMinX = CutValue(valueMinX, (-1) * (int)Math.Pow(2, 31), (int)Math.Pow(2, 31) - 1);
valueMaxX = CutValue(valueMaxX, (-1) * (int)Math.Pow(2, 31), (int)Math.Pow(2, 31) - 1);
valueMinY = CutValue(valueMinY, (-1) * (int)Math.Pow(2, 31), (int)Math.Pow(2, 31) - 1);
valueMaxY = CutValue(valueMaxY, (-1) * (int)Math.Pow(2, 31), (int)Math.Pow(2, 31) - 1);
RTC5Wrap.n_wait_for_encoder_in_range(m_deviceNo, valueMinX, valueMaxX, valueMinY, valueMaxY);// valueMin, valueMax);
}
public override void SetFlyX(double encoderResolution)
{
double scale = encoderResolution * m_ScaleXYFactor / 1000; // 단위는 bits/count
if (scale != 0) {
if (Math.Abs(scale) < 1.0 / 256.0 || 16000 < Math.Abs(scale)) {
throw new ArgumentOutOfRangeException("encoderResolution");
}
}
RTC5Wrap.n_set_fly_x(m_deviceNo, scale);
}
public override void SetFlyY(double encoderResolution)
{
double scale = encoderResolution * m_ScaleXYFactor / 1000; // 단위는 bits/count
if (scale != 0) {
if (Math.Abs(scale) < 1.0 / 256.0 || 16000 < Math.Abs(scale)) {
throw new ArgumentOutOfRangeException("encoderResolution");
}
}
RTC5Wrap.n_set_fly_y(m_deviceNo, scale);
}
public override void SetRotateCenter(double posX, double posY, eFunctionType type = eFunctionType.COMMAND)
{
int bitX = Convert.ToInt32(posX * m_ScaleXYFactor); // 단위는 count
int bitY = Convert.ToInt32(posY * m_ScaleXYFactor); // 단위는 count
if (type == eFunctionType.COMMAND) {
RTC5Wrap.n_set_rot_center(m_deviceNo, bitX, bitY);
} else {
RTC5Wrap.n_set_rot_center_list(m_deviceNo, bitX, bitY);
}
}
public override void SetFlyRotate(double encoderResolution)
{
double scale = encoderResolution; // 단위는 count
RTC5Wrap.n_set_fly_rot(m_deviceNo, scale);
}
public override void SetFlyRotatePos(double encoderResolution)
{
double scale = encoderResolution; // 단위는 bits/count
RTC5Wrap.n_set_fly_rot_pos(m_deviceNo, scale);
}
public override void ActivateFlyXY(double encoderResolutionX, double encoderResolutionY)
{
double scaleX = encoderResolutionX * m_ScaleXYFactor / 1000; // 단위는 bits/count
double scaleY = encoderResolutionY * m_ScaleXYFactor / 1000; // 단위는 bits/count
if (scaleX != 0) {
if (Math.Abs(scaleX) < 1.0 / 256.0 || 16000 < Math.Abs(scaleX)) {
throw new ArgumentOutOfRangeException("encoderResolution");
}
}
if (scaleY != 0) {
if (Math.Abs(scaleY) < 1.0 / 256.0 || 16000 < Math.Abs(scaleY)) {
throw new ArgumentOutOfRangeException("encoderResolution");
}
}
RTC5Wrap.n_activate_fly_xy(m_deviceNo, scaleX, scaleY);
}
public override void ActivateFly1Axis(int axis, int mode, double scale, int offset)
{
}
public override void Fly_Return(double x, double y)
{
CommandPosX = x;
CommandPosY = y;
int nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
int nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
RTC5Wrap.n_fly_return(m_deviceNo, nX, nY);
}
public override void ParkPosition(double posX, double posY, eParkType type = eParkType.VirtualImage)
{
int nX = Convert.ToInt32(posX * m_ScaleXYFactor);
int nY = Convert.ToInt32(posY * m_ScaleXYFactor);
RTC5Wrap.n_park_position(m_deviceNo, (uint)type, nX, nY);
}
public override void ParkReturn(double posX, double posY, eParkType type = eParkType.VirtualImage)
{
int nX = Convert.ToInt32(posX * m_ScaleXYFactor);
int nY = Convert.ToInt32(posY * m_ScaleXYFactor);
RTC5Wrap.n_park_return(m_deviceNo, (uint)type, nX, nY);
}
public override void InitFly2D(int offsetX = 0, int offsetY = 0)
{
RTC5Wrap.n_init_fly_2d(m_deviceNo, offsetX, offsetY);
}
public override void SimulateEncoder(uint EncoderNo)
{
RTC5Wrap.n_simulate_encoder(m_deviceNo, EncoderNo);
}
public override void SetControlMode(uint mode)
{
RTC5Wrap.n_set_control_mode(m_deviceNo, mode);
}
public override void SetLaesrDelay(int laserOnDelay, uint laserOffDelay)
{
const double delayScale = 0.5; //1bit당 0.5us
RTC5Wrap.n_set_laser_delays(m_deviceNo, Convert.ToInt32(laserOnDelay / delayScale), Convert.ToUInt32(laserOffDelay / delayScale));
}
public override void SetScannerDelay(uint jumpDelay, uint markDelay, uint arcDelay)
{
const double delayScale = 10;//1bit당 10us
RTC5Wrap.n_set_scanner_delays(m_deviceNo, Convert.ToUInt32(jumpDelay / delayScale), Convert.ToUInt32(markDelay / delayScale), Convert.ToUInt32(arcDelay / delayScale));
}
public override void SetJumpSpeedCtrl(double speed)
{
double targetSpeed = (speed * m_ScaleXYFactor) / 1000;
RTC5Wrap.n_set_jump_speed_ctrl(m_deviceNo, targetSpeed);
}
public override void SetJumpSpeed(double speed)
{
double targetSpeed = (speed * m_ScaleXYFactor) / 1000;
RTC5Wrap.n_set_jump_speed(m_deviceNo, targetSpeed);
}
public override void SetMarkSpeed(double speed)
{
double targetSpeed = (speed * m_ScaleXYFactor) / 1000;
RTC5Wrap.n_set_mark_speed(m_deviceNo, targetSpeed);
}
public override void SetStartList(eListNo no)
{
RTC5Wrap.n_set_start_list(m_deviceNo, Convert.ToUInt32(no));
}
public override uint LoadList(eListNo no)
{
return RTC5Wrap.n_load_list(m_deviceNo, Convert.ToUInt32(no), 0);
}
public override void SetEndList()
{
RTC5Wrap.n_set_end_of_list(m_deviceNo);
}
public override void ExecuteList(eListNo no)
{
RTC5Wrap.n_execute_list(m_deviceNo, Convert.ToUInt32(no));
}
public override void StartLoop()
{
RTC5Wrap.n_start_loop(m_deviceNo);
}
public override void QuitLoop()
{
RTC5Wrap.n_quit_loop(m_deviceNo);
}
public override void AutoChange()
{
RTC5Wrap.n_auto_change(m_deviceNo);
}
public override bool GetBusyStatus()
{
uint status;
uint position;
RTC5Wrap.n_get_status(m_deviceNo, out status, out position);
//return (status != 0);
if (status != 0) {
return true;
} else {
return false;
}
}
public override void StopExecution()
{
RTC5Wrap.n_stop_execution(m_deviceNo);
}
public override uint GetRTCVersion()
{
return RTC5Wrap.n_get_rtc_version(m_deviceNo);
}
public override uint GetDLLVersion()
{
return RTC5Wrap.get_dll_version();
}
public override void SetLaserTiming(uint periodHz, uint laser1PulseWidthUs, uint laser2PulseWidthUs) //단위는 Khz, us임
{
//uint halfPeriodBit = (32 / periodkHz) * 1000; //KHz를 halfPeriod bit로 변경함
uint halfPeriodBit = (uint)((32.0 / (double)periodHz) * 1000000.0); //KHz를 halfPeriod bit로 변경함
uint laser1PulseWidthBit = laser1PulseWidthUs * 64;
uint laser2PulseWidthBit = laser2PulseWidthUs * 64;
RTC5Wrap.n_set_laser_timing(m_deviceNo
, halfPeriodBit
, laser1PulseWidthBit
, laser2PulseWidthBit
, 1);
}
public override void SetStandby(uint periodkHz, uint laserPulseWidthUs) //단위는 Khz, us임
{
uint periodHz = periodkHz;
//uint halfPeriodBit = (32 / periodkHz) * 1000; //KHz를 halfPeriod bit로 변경함
uint halfPeriodBit = (uint)((32.0 / (double)periodHz) * 1000000.0); //KHz를 halfPeriod bit로 변경함
uint laserPulseWidthBit = laserPulseWidthUs * 64;
RTC5Wrap.n_set_standby(m_deviceNo, halfPeriodBit, laserPulseWidthBit);
}
public override void SetLaserMode(eLaserMode mode)
{
RTC5Wrap.n_set_laser_mode(m_deviceNo, (uint)mode);
}
public override void SetLaserControl(uint ctrl)
{
RTC5Wrap.n_set_laser_control(m_deviceNo, ctrl);
}
public override void SetFirstPulseKiller(uint width) //단위는 us->bit 로 변경해야 함
{
uint FirstPulseKillerBit = width * 64;
RTC5Wrap.n_set_firstpulse_killer(m_deviceNo, FirstPulseKillerBit);
}
public override void LaserSignalOn()
{
RTC5Wrap.n_laser_signal_on(m_deviceNo);
}
public override void LaserSignalOff()
{
RTC5Wrap.n_laser_signal_off(m_deviceNo);
}
///
/// 지정한 시간 시간만큼 Laser Active 신호를 켜주는 리스트 함수
///
/// 시간[ms]
public override void LaserOnList(double interval)
{
uint intervalInBits = (uint)(interval * 100); // 1[bit] = 10[us]
RTC5Wrap.n_laser_on_list(m_deviceNo, intervalInBits);
}
///
/// Laser Active가 Off된 상태에서 지정한 시간 시간만큼 delay를 추가하는 함수
///
/// 시간[ms]
public override void LongDelay(uint delay)
{
uint delayInBits = delay * 100; // 1[bit] = 10[us]
RTC5Wrap.n_long_delay(m_deviceNo, delayInBits);
}
public override void SetAngle(double angle/*degree*/, uint atOnce, eFunctionType type = eFunctionType.COMMAND)
{
if (type == eFunctionType.COMMAND) {
RTC5Wrap.n_set_angle(m_deviceNo, m_PrimaryHeadNo, angle, atOnce);
} else {
RTC5Wrap.n_set_angle_list(m_deviceNo, m_PrimaryHeadNo, angle, atOnce);
}
}
public override void SetOffset(double offsetX, double offsetY, uint atOnce, eFunctionType type = eFunctionType.COMMAND)
{
int nX = Convert.ToInt32(offsetX * m_ScaleXYFactor);
int nY = Convert.ToInt32(offsetY * m_ScaleXYFactor);
if (type == eFunctionType.COMMAND) {
RTC5Wrap.n_set_offset(m_deviceNo, m_PrimaryHeadNo, nX, nY, atOnce);
} else {
RTC5Wrap.n_set_offset_list(m_deviceNo, m_PrimaryHeadNo, nX, nY, atOnce);
}
}
public override void DisableLaser()
{
RTC5Wrap.n_disable_laser(m_deviceNo);
}
public override void EnableLaser()
{
RTC5Wrap.n_enable_laser(m_deviceNo);
}
public override void ParaLaserOnPulsesList(double period, uint pulses, float powerValue)
{
uint periodbit = 0;
if (period >= 0) {
periodbit = (uint)(period * 100);
}
uint pulsesbit = (uint)pulses;
uint targetValue = (uint)(powerValue * 40.95); // 인수 범위는 0 ~ 4095
RTC5Wrap.n_para_laser_on_pulses_list(m_deviceNo, periodbit, pulsesbit, targetValue);
}
//Ramping 기능
public override void ParaMarkAbs(double x, double y, float power)
{
CommandPosX = x;
CommandPosY = y;
int nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
int nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
uint targetValue = (uint)(power * 40.95); // 인수 범위는 0 ~ 4095
RTC5Wrap.n_para_mark_abs(m_deviceNo, nX, nY, targetValue);
}
public override void ParaMarkRel(double x, double y, float power)
{
CommandPosX += x;
CommandPosY += y;
int nX = Convert.ToInt32(x * m_ScaleXYFactor);
int nY = Convert.ToInt32(y * m_ScaleXYFactor);
uint targetValue = (uint)(power * 40.95); // 인수 범위는 0 ~ 4095
RTC5Wrap.n_para_mark_rel(m_deviceNo, nX, nY, targetValue);
}
public override void ParaJumpAbs(double x, double y, float power)
{
CommandPosX = x;
CommandPosY = y;
int nX = Convert.ToInt32(CommandPosX * m_ScaleXYFactor);
int nY = Convert.ToInt32(CommandPosY * m_ScaleXYFactor);
uint targetValue = (uint)(power * 40.95); // 인수 범위는 0 ~ 4095
RTC5Wrap.n_para_jump_abs(m_deviceNo, nX, nY, targetValue);
}
public override void ParaJumpRel(double x, double y, float power)
{
CommandPosX += x;
CommandPosY += y;
int nX = Convert.ToInt32(x * m_ScaleXYFactor);
int nY = Convert.ToInt32(y * m_ScaleXYFactor);
uint targetValue = (uint)(power * 40.95); // 인수 범위는 0 ~ 4095
RTC5Wrap.n_para_jump_rel(m_deviceNo, nX, nY, targetValue);
}
public override void SetVectorControl(uint portNo, uint value)
{
RTC5Wrap.n_set_vector_control(m_deviceNo, portNo, value);
}
//측정 기능
public override void StopTrigger()
{
RTC5Wrap.n_stop_trigger(m_deviceNo);
}
public override void SetTrigger(uint period/*㎲*/, eRecordSignal signal1, eRecordSignal signal2, eRecordSignal signal3, eRecordSignal signal4)
{
uint targetPeriod = period / 10;//1bit = 10㎲
RTC5Wrap.n_set_trigger4(m_deviceNo, targetPeriod, (uint)signal1, (uint)signal2, (uint)signal3, (uint)signal4);
}
public override void SetTrigger(uint period/*㎲*/, eRecordSignal signal1, eRecordSignal signal2)
{
uint targetPeriod = period / 10;//1bit = 10㎲
RTC5Wrap.n_set_trigger(m_deviceNo, targetPeriod, (uint)signal1, (uint)signal2);
}
public override void Measurement_status(out uint busy, out uint pos)
{
RTC5Wrap.n_measurement_status(m_deviceNo, out busy, out pos);
}
public override uint ReadStatus()
{
return RTC5Wrap.n_read_status(m_deviceNo);
}
public override void GetWaveForm(uint channel, uint number, out int[] data)
{
data = new int[number];
for (int i = 0; i < m_getWaveformPtr.Length; i++) {
m_getWaveformPtr[i] = 0;
}
RTC5Wrap.n_get_waveform(m_deviceNo, channel, number, m_getWaveformPtr);
for (int i = 0; i < data.Length; i++) {
data[i] = m_getWaveformPtr[i];
}
}
//안오산-170224-Wobbel모드 추가(V1.7.0)
//set_wobbel_mode
public override void SetWobbelMode(bool wobbelEnable, double transversal, double longitudinal, double frequency, int shape)
{
//wobbel 모드 사용 안할 경우 Frequency 0
if (!wobbelEnable) {
frequency = 0;
}
//Amplitude 설정(Transversal, Longitudinal
uint nTrans = Convert.ToUInt32(transversal * m_ScaleXYFactor);
uint nLong = Convert.ToUInt32(longitudinal * m_ScaleXYFactor);
int mode = (int)shape;
RTC5Wrap.n_set_wobbel_mode(m_deviceNo, nTrans, nLong, frequency, mode);
}
public override void SetWobbelDirection(int dX, int dY)
{
RTC5Wrap.n_set_wobbel_direction(m_deviceNo, dX, dY);
}
public override void SetWobbelVector(double tansversal, double longitudinal, uint period, float power)
{
RTC5Wrap.n_set_wobbel_vector(m_deviceNo, tansversal, longitudinal, period, power);
}
public override void ConfigLaserSignal(eLaserSignal pin2, eLaserSignal pin1, eLaserSignal pin9)
{
uint iPin2 = (uint)pin2;
uint iPin1 = (uint)pin1;
uint iPin9 = (uint)pin9;
uint config = iPin9 << 4 | iPin1 << 2 | iPin2;
RTC5Wrap.n_config_laser_signals(m_deviceNo, config);
}
public override void SelectCorrectionTable(int no)
{
RTC5Wrap.n_select_cor_table(m_deviceNo, (uint)no, 0);
}
public override void SetEthernetConfigLinkLoss(eEthConfigLinkLossMode mode)
{
}
public override int CheckEthernetConnection(out uint errorCode)
{
errorCode = 0;
return 0;
}
#region 리스트 실행 시간 측정
///
/// Delayed Short List Command
/// Stores the current value of the RTC6 timer and resets it to zero.
///
public override void SaveAndRestartTimer()
{
RTC5Wrap.save_and_restart_timer();
}
///
/// Ctrl Command
/// Returns the RTC5 timer value (without resetting it to zero). It has been stored during the most recent call of save_and_restart_timer.
///
/// RTC5 timer value in seconds. As a 64-bit IEEE floating point value.
public override double GetTime()
{
return RTC5Wrap.get_time();
}
public override void SetConfigList(uint mem1, uint mem2)
{
RTC5Wrap.n_config_list(m_deviceNo, mem1, mem2);
}
public override uint GetListSpace()
{
return RTC5Wrap.n_get_list_space(m_deviceNo);
}
#endregion
// 기존 추상함수 아닌 3개 항목 추상함수로 추가
//ExecuteUpdateParameterList는 Initialize에 직접구현할수밖에.. config의 항목 쓰려면..
public override uint LoadProgramFile(string fileName)
{
return RTC5Wrap.n_load_program_file(m_deviceNo, fileName);
}
public override uint LoadCorrectionFile(string fileName, uint correctionNo, bool use3DMode)
{
uint dimm = (use3DMode) ? 3U : 2U;
return RTC5Wrap.n_load_correction_file(m_deviceNo, fileName, correctionNo, dimm);
}
public static int CutValue(int value, int min, int max)
{
if (value > max) {
return max;
} else if (value < min) {
return min;
} else {
return value;
}
}
public override void SetLaserPinOutList(uint pins)
{
RTC5Wrap.set_laser_pin_out_list(pins);
}
public override void SetPortDefault(uint port, uint value)
{
RTC5Wrap.set_port_default(port, value);
}
public override void SetLaserPinOut(uint pins)
{
RTC5Wrap.set_laser_pin_out(pins);
}
public override uint GetLastError()
{
return RTC5Wrap.get_last_error();
}
}
}