8#ifndef zaberBinaryStage_hpp
9#define zaberBinaryStage_hpp
16#include "../../libMagAOX/libMagAOX.hpp"
29template <
class parentT>
165 if( parent ==
nullptr )
167 throw mx::exception( mx::error_t::invalidarg,
"parent was null on construction of zaberBinaryStage" );
177 int name(
const std::string &n );
283 uint8_t commandNumber,
285 uint8_t expectedReply
290 uint8_t commandNumber,
297 uint8_t settingNumber
372template <
class parentT>
378template <
class parentT>
385template <
class parentT>
391template <
class parentT>
398template <
class parentT>
401 return m_deviceAddress;
404template <
class parentT>
407 m_deviceAddress = da;
411template <
class parentT>
417template <
class parentT>
424template <
class parentT>
427 return m_commandStatus;
430template <
class parentT>
433 return m_deviceStatus;
436template <
class parentT>
442template <
class parentT>
445 return m_lastHomed.tv_sec;
448template <
class parentT>
454template <
class parentT>
457 return m_knobEnabled;
460template <
class parentT>
466template <
class parentT>
472template <
class parentT>
478template <
class parentT>
481 return m_targetSpeed;
484template <
class parentT>
487 m_targetSpeed = speed;
491template <
class parentT>
497template <
class parentT>
503template <
class parentT>
509template <
class parentT>
515template <
class parentT>
521template <
class parentT>
527template <
class parentT>
533template <
class parentT>
539template <
class parentT>
545template <
class parentT>
551template <
class parentT>
557template <
class parentT>
563template <
class parentT>
569template <
class parentT>
575template <
class parentT>
581template <
class parentT>
587template <
class parentT>
593template <
class parentT>
599template <
class parentT>
605template <
class parentT>
611template <
class parentT>
617template <
class parentT>
623template <
class parentT>
629template <
class parentT>
631 int32_t &response, z_port port, uint8_t commandNumber, int32_t data, uint8_t expectedReply )
633 if( m_deviceAddress < 1 )
636 std::format(
"stage {} with s/n {} not found in system.", m_name, m_serial ) );
641 if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
650 if(
zb_encode( command,
static_cast<uint8_t
>( m_deviceAddress ), commandNumber, data ) !=
Z_SUCCESS )
655 if(
zb_send( port, command ) != 6 )
664 if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
672 if( reply[0] !=
static_cast<uint8_t
>( m_deviceAddress ) )
675 std::format(
"unexpected reply from device {} while querying {}", reply[0], m_name ) );
678 if( reply[1] == 255 )
683 std::format(
"device {} command {} returned error {}", m_name, commandNumber, errorCode ) );
686 if( reply[1] != expectedReply )
689 std::format(
"device {} returned reply {} while expecting {}", m_name, reply[1], expectedReply ) );
697 m_commandStatus =
true;
701template <
class parentT>
704 if( m_deviceAddress < 1 )
707 std::format(
"stage {} with s/n {} not found in system.", m_name, m_serial ) );
712 if( m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1 )
721 if(
zb_encode( command,
static_cast<uint8_t
>( m_deviceAddress ), commandNumber, data ) !=
Z_SUCCESS )
726 if(
zb_send( port, command ) != 6 )
731 m_commandStatus =
true;
735template <
class parentT>
738 return queryCommand( value, port, cmdReturnSetting, settingNumber, settingNumber );
741template <
class parentT>
745 int rv = getSetting( value, port, cmdSetMaximumPosition );
755template <
class parentT>
758 if( m_hasParkPos && m_rawPos == m_parkPos )
770template <
class parentT>
774 int rv = getSetting( value, port, cmdSetDeviceMode );
779 m_knobEnabled = !( value & modeDisablePotentiometer );
784template <
class parentT>
787 bool wasHoming = m_homing;
790 int rv = queryCommand( status, port, cmdReturnStatus, 0, cmdReturnStatus );
798 m_deviceStatus =
'I';
802 m_deviceStatus =
'B';
805 m_homing = ( status == 1 );
808 rv = queryCommand( pos, port, cmdReturnCurrentPosition, 0, cmdReturnCurrentPosition );
816 rv = getWarnings( port );
822 return updateLastHomed( wasHoming );
825template <
class parentT>
832template <
class parentT>
836 int rv = getSetting( mode, port, cmdSetDeviceMode );
842 mode |= modeDisableAutoReply;
844 mode &= ~modeDisablePotentiometer;
846 mode |= modeDisablePotentiometer;
848 rv = sendCommandNoReply( port, cmdSetDeviceMode, mode );
855 rv = getSetting( appliedMode, port, cmdSetDeviceMode );
861 bool knobOk = enable ? !( appliedMode & modeDisablePotentiometer )
862 : ( appliedMode & modeDisablePotentiometer );
864 if( !knobOk || !( appliedMode & modeDisableAutoReply ) )
867 std::format(
"device {} did not apply requested device mode {}, got {}", m_name, mode, appliedMode ) );
873template <
class parentT>
876 int rv = sendCommandNoReply( port, cmdSetTargetSpeed, speed );
882 int32_t appliedSpeed;
883 rv = getSetting( appliedSpeed, port, cmdSetTargetSpeed );
889 if( appliedSpeed != speed )
892 std::format(
"device {} reported target speed {} after requesting {}", m_name, appliedSpeed, speed ) );
898template <
class parentT>
901 int rv = sendCommandNoReply( port, cmdSetHoldCurrent, value );
907 int32_t appliedValue;
908 rv = getSetting( appliedValue, port, cmdSetHoldCurrent );
914 if( appliedValue != value )
917 std::format(
"device {} reported hold current {} after requesting {}", m_name, appliedValue, value ) );
923template <
class parentT>
926 int rv = sendCommandNoReply( port, cmdStop, 0 );
937template <
class parentT>
943template <
class parentT>
946 int rv = sendCommandNoReply( port, cmdHome, 0 );
958template <
class parentT>
961 int rv = sendCommandNoReply( port, cmdStoreCurrentPosition, parkPositionRegister );
967 rv = recallParkPosition( port );
973 rv = setHoldCurrent( port, 0 );
982template <
class parentT>
989template <
class parentT>
992 int32_t storedPosition;
994 queryCommand( storedPosition, port, cmdReturnStoredPosition, parkPositionRegister, cmdReturnStoredPosition );
997 m_hasParkPos =
false;
1001 m_parkPos = storedPosition;
1002 m_hasParkPos =
true;
1003 m_parked = ( m_rawPos == m_parkPos );
1007template <
class parentT>
1010 if( !m_hasStateFile || !m_stateFileParked || !m_hasParkPos )
1015 if( m_stateFileRawPos != m_parkPos )
1018 std::format(
"parked state mismatch for {}: disk {} device {}", m_name, m_stateFileRawPos, m_parkPos ) );
1021 int rv = setHoldCurrent( port, 0 );
1027 rv = sendCommandNoReply( port, cmdSetCurrentPosition, m_stateFileRawPos );
1033 int32_t restoredPos;
1034 rv = queryCommand( restoredPos, port, cmdReturnCurrentPosition, 0, cmdReturnCurrentPosition );
1040 if( restoredPos != m_stateFileRawPos )
1043 std::format(
"device {} restored position {} but expected {}", m_name, restoredPos, m_stateFileRawPos ) );
1046 m_rawPos = restoredPos;
1047 m_tgtPos = restoredPos;
1052template <
class parentT>
1057 int rv = unpark( port );
1064 int rv = sendCommandNoReply( port, cmdMoveAbsolute, rawPos );
1075template <
class parentT>
1102template <
class parentT>
1108 int rv = getSetting( mode, port, cmdSetDeviceMode );
1114 if( ( mode & modeHomeStatus ) == 0 )
1123template <
class parentT>
1126 if( !m_homing && !m_warnWR && m_tgtPos == 0 && m_rawPos == 0 && ( wasHoming || m_lastHomed.tv_sec == 0 ) )
1128 if( clock_gettime( CLOCK_ISIO, &m_lastHomed ) < 0 )
1137template <
class parentT>
1140 m_commandStatus =
true;
1141 m_deviceStatus =
'U';
1148template <
class parentT>
1151 fout << m_rawPos <<
'\n';
1157 fout << m_parked <<
'\n';
1163 fout << m_maxPos <<
'\n';
1169 fout << m_lastHomed.tv_sec <<
'\n';
1178template <
class parentT>
1214 m_hasParkPos = parked;
1215 m_hasStateFile =
true;
1216 m_stateFileRawPos = rawPos;
1217 m_stateFileParked = parked;
1219 m_lastHomed.tv_sec = lastHomed;
1220 m_lastHomed.tv_nsec = 0;
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
A class to manage the details of one binary-protocol stage in a Zaber system.
static constexpr int32_t parkPositionRegister
Stored-position register used to persist the MagAO-X parked position.
bool m_commandStatus
Whether the most recent command was accepted.
int targetSpeed(const int32_t &speed)
Set the configured target speed.
int park(z_port port)
Mark the stage parked using MagAO-X bookkeeping semantics.
int getParked(z_port port)
Get the parked state for MagAO-X compatibility.
int stop(z_port port)
Stop the stage.
int updatePos(z_port port)
Update the current position and derived motion state.
bool m_warn
Whether any warning-equivalent condition is active.
int sendCommandNoReply(z_port port, uint8_t commandNumber, int32_t data)
Send a command for which no reply is expected.
bool warnWV()
Get the WV warning flag.
int updateTemp(z_port port)
Update the stage temperature, if supported.
bool warnNC()
Get the NC warning flag.
timespec m_lastHomed
Time stamp of the last successful home operation.
bool warnNJ()
Get the NJ warning flag.
bool warn()
Get whether any warning-equivalent flag is set.
long maxPos()
Get the maximum position.
bool warnWH()
Get the WH warning flag.
float m_temp
Last reported stage temperature. Firmware 5.35 does not expose this directly.
int deviceAddress()
Get the device address.
char m_deviceStatus
Current device state mapped to ASCII-app semantics.
bool warnFS()
Get the FS warning flag.
int getMaxPos(z_port port)
Get the maximum position from the device.
bool warnFE()
Get the FE warning flag.
std::string serial()
Get the stage serial number.
bool m_hasStateFile
Whether a parked state file has been loaded from disk.
bool warningState()
Get whether any warning-equivalent flag is set.
long m_maxPos
Maximum position in microsteps.
commandCodes
Binary protocol command numbers used by the T-LSM firmware 5.xx implementation.
@ cmdMoveToStoredPosition
@ cmdReturnCurrentPosition
@ cmdStoreCurrentPosition
@ cmdReturnFirmwareVersion
@ cmdReturnStoredPosition
char deviceStatus()
Get the current device status.
int m_axisNumber
Axis number placeholder for future multi-axis support.
zaberBinaryStage(parentT *parent)
Construct the stage helper.
zaberBinaryStage()=delete
Default constructor deleted because stages require a parent app.
std::string m_serial
Configured stage serial number.
bool warnFB()
Get the FB warning flag.
int getKnob(z_port port)
Get the knob enabled status.
int readStateFile(std::ifstream &fin)
Read the state file used by the low-level app.
int getSetting(int32_t &value, z_port port, uint8_t settingNumber)
Return a setting value from the device.
bool warnNU()
Get the NU warning flag.
bool warnUNK()
Get the unknown-warning flag.
bool warnND()
Get the ND warning flag.
int serial(const std::string &s)
Set the stage serial number.
long m_tgtPos
Last target position sent to the device in microsteps.
bool warnFQ()
Get the FQ warning flag.
int32_t targetSpeed()
Get the configured target speed.
int axisNumber(const int &an)
Set the axis number.
bool m_warnFD
Driver disabled warning flag.
int unpark(z_port port)
Clear the parked bookkeeping state.
float temp()
Get the driver temperature.
int restoreParkedState(z_port port)
Restore parked state after a power cycle if device and disk state agree.
int m_deviceAddress
Current binary device address.
int name(const std::string &n)
Set the stage name.
int unsetWarnings()
Clear all warning flags.
bool homing()
Get the homing state.
bool m_homing
Whether the stage is currently homing.
long m_rawPos
Current raw position in microsteps.
long rawPos()
Get the current raw position.
int getWarnings(z_port port)
Refresh warning-equivalent state from firmware 5.xx information.
bool warnFD()
Get the driver-disabled warning flag.
bool warnFP()
Get the FP warning flag.
int32_t m_targetSpeed
Configured target speed command value for this stage.
bool warnWR()
Get the WR warning flag.
parentT * m_parent
Parent application used for logging and power-state checks.
int onPowerOff()
Clear transient state on power-off.
bool warnWT()
Get the WT warning flag.
bool warnNI()
Get the NI warning flag.
int moveAbs(z_port port, long rawPos)
Move to a new absolute position.
modeBits
Device-mode bits used by the implementation.
@ modeDisablePotentiometer
bool m_warnFQ
Device-specific warning flag placeholders retained for API compatibility.
int deviceAddress(const int &da)
Set the device address.
bool commandStatus()
Get the status of the last command.
std::string name()
Get the stage name.
long m_stateFileRawPos
Raw position loaded from the parked state file.
int estop(z_port port)
Emergency-stop the stage.
int enableKnob(z_port port, bool enable)
Disable the manual knob and asynchronous command replies.
bool m_hasParkPos
Whether a parked position has been recovered from device non-volatile memory.
long tgtPos()
Get the target raw position.
long m_parkPos
Emulated parked position in microsteps.
int setTargetSpeed(z_port port, int32_t speed)
Set the target speed used for absolute and relative moves.
int queryCommand(int32_t &response, z_port port, uint8_t commandNumber, int32_t data, uint8_t expectedReply)
Send a command and wait for the corresponding binary reply.
bool warnWM()
Get the WM warning flag.
int writeStateFile(std::ofstream &fout)
Write the state file used by the low-level app.
int axisNumber()
Get the axis number.
bool warnWP()
Get the WP warning flag.
int updateLastHomed(bool wasHoming)
Refresh the stored last-home timestamp when a home completion is detected.
bool warnWL()
Get the WL warning flag.
int setHoldCurrent(z_port port, int32_t value)
Set the hold current used while the stage is idle.
bool m_parked
Whether MagAO-X currently considers this stage parked.
std::string m_name
Configured stage name used in INDI properties.
int recallParkPosition(z_port port)
Recall the MagAO-X parked position from device non-volatile memory.
time_t lastHomed()
Get the last home time.
int home(z_port port)
Home the stage.
int parked()
Get the parked state.
bool m_knobEnabled
whether potentiometer knob is enabled
bool warnFT()
Get the FT warning flag.
bool knobEnabled()
Get the knob state.
bool m_stateFileParked
Parked flag loaded from the parked state file.
Provides a set of functions for interacting with Zaber devices in the binary protocol.
int zb_decode(int32_t *destination, const uint8_t *reply)
int zb_encode(uint8_t *destination, uint8_t device_number, uint8_t command_number, int32_t data)
int zb_send(z_port port, const uint8_t *command)
int zb_receive(z_port port, uint8_t *destination)