Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 113 additions & 30 deletions DeviceAdapters/EvidentIX85Win/EvidentIX85Win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,13 @@ int EvidentNosepiece::Initialize()
AddAllowedValue("Set-Focus-Near-Limit", "Set");
AddAllowedValue("Set-Focus-Near-Limit", "Clear");

// Create writable float property to set the near limit by typing a value
pAct = new CPropertyAction(this, &EvidentNosepiece::OnSetNearLimitValue);
ret = CreateProperty("Set-Focus-Near-Limit-um", "0.0", MM::Float, false, pAct);
if (ret != DEVICE_OK)
return ret;
SetPropertyLimits("Set-Focus-Near-Limit-um", 0.0, FOCUS_MAX_POS * FOCUS_STEP_SIZE_UM);

// Query parfocal settings from microscope
ret = QueryParfocalSettings();
if (ret != DEVICE_OK)
Expand Down Expand Up @@ -939,6 +946,74 @@ int EvidentNosepiece::OnSetNearLimit(MM::PropertyBase* pProp, MM::ActionType eAc
return DEVICE_OK;
}

int EvidentNosepiece::OnSetNearLimitValue(MM::PropertyBase* pProp, MM::ActionType eAct)
{
if (eAct == MM::BeforeGet)
{
EvidentHubWin* hub = GetHub();
if (!hub)
return DEVICE_ERR;

long nosepiecePos = hub->GetModel()->GetPosition(DeviceType_Nosepiece);
if (nosepiecePos >= 1 && nosepiecePos <= (long)nearLimits_.size())
pProp->Set(nearLimits_[nosepiecePos - 1] * FOCUS_STEP_SIZE_UM);
else
pProp->Set(0.0);
}
Comment thread
nicost marked this conversation as resolved.
else if (eAct == MM::AfterSet)
{
EvidentHubWin* hub = GetHub();
if (!hub)
return DEVICE_ERR;

long nosepiecePos = hub->GetModel()->GetPosition(DeviceType_Nosepiece);
if (nosepiecePos < 1 || nosepiecePos > (long)nearLimits_.size())
return ERR_INVALID_PARAMETER;

double val;
pProp->Get(val);
long newLimit = static_cast<long>(val / FOCUS_STEP_SIZE_UM);
if (newLimit < FOCUS_MIN_POS) newLimit = FOCUS_MIN_POS;
if (newLimit > FOCUS_MAX_POS) newLimit = FOCUS_MAX_POS;

long oldLimit = nearLimits_[nosepiecePos - 1];
nearLimits_[nosepiecePos - 1] = newLimit;

std::ostringstream cmd;
cmd << CMD_FOCUS_NEAR_LIMIT << TAG_DELIMITER;
for (size_t i = 0; i < nearLimits_.size(); i++)
{
if (i > 0)
cmd << DATA_DELIMITER;
cmd << nearLimits_[i];
}

std::string response;
int ret = hub->ExecuteCommand(cmd.str(), response);
if (ret != DEVICE_OK)
{
nearLimits_[nosepiecePos - 1] = oldLimit;
pProp->Set(oldLimit * FOCUS_STEP_SIZE_UM);
return ret;
}

if (!IsPositiveAck(response, CMD_FOCUS_NEAR_LIMIT))
{
nearLimits_[nosepiecePos - 1] = oldLimit;
pProp->Set(oldLimit * FOCUS_STEP_SIZE_UM);
return ERR_NEGATIVE_ACK;
}

pProp->Set(newLimit * FOCUS_STEP_SIZE_UM);

std::ostringstream logMsg;
Comment thread
nicost marked this conversation as resolved.
logMsg << "Set near limit for objective " << nosepiecePos
<< " to " << (newLimit * FOCUS_STEP_SIZE_UM) << " um";
LogMessage(logMsg.str().c_str());
}
return DEVICE_OK;
}

int EvidentNosepiece::OnParfocalPosition(MM::PropertyBase* pProp, MM::ActionType eAct)
{
if (eAct == MM::BeforeGet)
Expand Down Expand Up @@ -3583,18 +3658,12 @@ int EvidentAutofocus::Initialize()
}
}

// Query initial AF limits
cmd = BuildQuery(CMD_AF_LIMIT);
ret = hub->ExecuteCommand(cmd, response);
if (ret == DEVICE_OK)
{
std::vector<std::string> params = ParseParameters(response);
if (params.size() >= 2 && params[0] != "X" && params[1] != "X")
{
nearLimit_ = ParseIntParameter(params[0]);
farLimit_ = ParseIntParameter(params[1]);
}
}
// The hardware clears AFL limits when remote mode is exited, so we do not
// overwrite nearLimit_/farLimit_ from the hardware here. Instead, mark
// zdcInitNeeded_ so InitializeZDC() will re-apply the adapter's stored
// limits (which include any values restored from a saved config file)
// before the first AF operation.
zdcInitNeeded_ = true;

// Create AF Status property (read-only)
CPropertyAction* pAct = new CPropertyAction(this, &EvidentAutofocus::OnAFStatus);
Expand Down Expand Up @@ -4384,6 +4453,14 @@ int EvidentAutofocus::FindFocusWithOffset()
long measuredZOffset = hub->GetModel()->GetMeasuredZOffset();
long targetZPos = currentZPos + measuredZOffset;

// Clamp to user-set AF search limits first, then enforce hardware bounds
// last so hardware limits always win regardless of what farLimit_/nearLimit_
// contain.
if (targetZPos < farLimit_) targetZPos = farLimit_;
if (targetZPos > nearLimit_) targetZPos = nearLimit_;
if (targetZPos < FOCUS_MIN_POS) targetZPos = FOCUS_MIN_POS;
if (targetZPos > FOCUS_MAX_POS) targetZPos = FOCUS_MAX_POS;

std::ostringstream logMsg;
logMsg << "Applying Z-offset: " << measuredZOffset <<
" steps (from " << currentZPos <<
Expand Down Expand Up @@ -4472,17 +4549,20 @@ int EvidentAutofocus::OnNearLimit(MM::PropertyBase* pProp, MM::ActionType eAct)
return ERR_INVALID_PARAMETER;
}

std::string cmd = BuildCommand(CMD_AF_LIMIT, static_cast<int>(newNear), static_cast<int>(farLimit_));
std::string response;
int ret = hub->ExecuteCommand(cmd, response);
if (ret != DEVICE_OK)
return ret;

if (!IsPositiveAck(response, CMD_AF_LIMIT))
return ERR_NEGATIVE_ACK;

nearLimit_ = newNear;

// AFL can only be set while AF is idle; if active, defer to InitializeZDC().
if (afStatus_ == 0)
{
std::string cmd = BuildCommand(CMD_AF_LIMIT, static_cast<int>(nearLimit_), static_cast<int>(farLimit_));
std::string response;
int ret = hub->ExecuteCommand(cmd, response);
if (ret != DEVICE_OK)
LogMessage("Warning: AFL command failed when setting near limit; will retry via InitializeZDC()");
else if (!IsPositiveAck(response, CMD_AF_LIMIT))
LogMessage("Warning: AFL negative ACK when setting near limit; will retry via InitializeZDC()");
}
Comment thread
nicost marked this conversation as resolved.

// Mark that ZDC needs re-initialization (deferred until next AF operation)
zdcInitNeeded_ = true;
}
Expand Down Expand Up @@ -4511,17 +4591,20 @@ int EvidentAutofocus::OnFarLimit(MM::PropertyBase* pProp, MM::ActionType eAct)
return ERR_INVALID_PARAMETER;
}

std::string cmd = BuildCommand(CMD_AF_LIMIT, static_cast<int>(nearLimit_), static_cast<int>(newFar));
std::string response;
int ret = hub->ExecuteCommand(cmd, response);
if (ret != DEVICE_OK)
return ret;

if (!IsPositiveAck(response, CMD_AF_LIMIT))
return ERR_NEGATIVE_ACK;

farLimit_ = newFar;

// AFL can only be set while AF is idle; if active, defer to InitializeZDC().
if (afStatus_ == 0)
{
std::string cmd = BuildCommand(CMD_AF_LIMIT, static_cast<int>(nearLimit_), static_cast<int>(farLimit_));
std::string response;
int ret = hub->ExecuteCommand(cmd, response);
if (ret != DEVICE_OK)
LogMessage("Warning: AFL command failed when setting far limit; will retry via InitializeZDC()");
else if (!IsPositiveAck(response, CMD_AF_LIMIT))
LogMessage("Warning: AFL negative ACK when setting far limit; will retry via InitializeZDC()");
}
Comment thread
nicost marked this conversation as resolved.

// Mark that ZDC needs re-initialization (deferred until next AF operation)
zdcInitNeeded_ = true;
}
Expand Down
1 change: 1 addition & 0 deletions DeviceAdapters/EvidentIX85Win/EvidentIX85Win.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class EvidentNosepiece : public CStateDeviceBase<EvidentNosepiece>
int OnObjectiveWD(MM::PropertyBase* pProp, MM::ActionType eAct);
int OnNearLimit(MM::PropertyBase* pProp, MM::ActionType eAct);
int OnSetNearLimit(MM::PropertyBase* pProp, MM::ActionType eAct);
int OnSetNearLimitValue(MM::PropertyBase* pProp, MM::ActionType eAct);
int OnParfocalPosition(MM::PropertyBase* pProp, MM::ActionType eAct);
int OnSetParfocalPosition(MM::PropertyBase* pProp, MM::ActionType eAct);
int OnParfocalEnabled(MM::PropertyBase* pProp, MM::ActionType eAct);
Expand Down
Loading