29 static std::unique_ptr<XAGYLWheel> xagylWheel(
new XAGYLWheel());
67 IUFillText(&FirmwareInfoT[FIRMWARE_PRODUCT],
"FIRMWARE_PRODUCT",
"Product",
69 IUFillText(&FirmwareInfoT[FIRMWARE_VERSION],
"FIRMWARE_VERSION",
"Version",
71 IUFillText(&FirmwareInfoT[FIRMWARE_SERIAL],
"FIRMWARE_SERIAL",
"Serial #",
77 IUFillNumber(&SettingsN[SETTING_SPEED],
"SETTING_SPEED",
"Speed",
"%.f",
79 IUFillNumber(&SettingsN[SETTING_JITTER],
"SETTING_JITTER",
"Jitter",
"%.f",
81 IUFillNumber(&SettingsN[SETTING_THRESHOLD],
"SETTING_THRESHOLD",
82 "Threshold",
"%.f", 10, 30, 1., 0.);
83 IUFillNumber(&SettingsN[SETTING_PW],
"SETTING_PW",
"Pulse",
"%.f",
84 100, 10000, 100., 0.);
92 "COMMAND_CLEAR_CALIBRATION Calibration",
"Clear Calibration",
95 "COMMAND_PERFORM_CALIBRAITON",
"Perform Calibration",
ISS_OFF);
137 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
139 tcflush(
PortFD, TCIOFLUSH);
142 if (!sendCommand(
cmd, res))
145 int firmware_version = 0;
146 int fw_rc = sscanf(res,
"%d", &firmware_version);
149 fw_rc = sscanf(res,
"FW %d", &firmware_version);
153 LOGF_ERROR(
"Unable to parse response <%s>", res);
157 m_FirmwareVersion = firmware_version;
161 if (m_FirmwareVersion < 3)
164 bool rc = getMaxFilterSlots();
167 LOG_ERROR(
"Unable to parse max filter slots.");
173 rc = getFilterPosition();
176 LOG_ERROR(
"Unable to initialize filter position.");
180 LOG_INFO(
"XAGYL is online. Getting filter parameters...");
189 char *names[],
int n)
193 if (strcmp(ResetSP.
name, name) == 0)
202 LOG_INFO(
"Executing hard reboot...");
206 LOG_INFO(
"Restarting and moving to filter position #1...");
209 case COMMAND_CLEAR_CALIBRATION:
213 case COMMAND_PERFORM_CALIBRAITON:
218 bool rc = reset(command);
222 LOG_ERROR(
"Error. Please reset device.");
238 char *names[],
int n)
244 if (strcmp(OffsetNP.
name, name) == 0)
248 bool rc_offset =
true;
250 for (
int i = 0; i < n; i++)
252 if (0 != strcmp(names[i], OffsetN[i].name))
255 int newOffset = values[i];
256 int curOffset = OffsetN[i].value;
258 if (newOffset != curOffset)
259 rc_offset &= setOffset(i + 1, newOffset - curOffset);
273 if (strcmp(SettingsNP.
name, name) == 0)
275 int newSpeed = -1, newJitter = -1, newThreshold = -1,
278 for (
int i = 0; i < n; i++)
280 if (!strcmp(names[i], SettingsN[
SET_SPEED].name))
281 newSpeed = values[i];
282 if (!strcmp(names[i], SettingsN[
SET_JITTER].name))
283 newJitter = values[i];
285 newThreshold = values[i];
287 newPulseWidth = values[i];
290 bool rc_speed =
true, rc_jitter =
true, rc_threshold =
true,
291 rc_pulsewidth =
true;
296 rc_speed = setMaximumSpeed(newSpeed);
304 rc_jitter &= setRelativeCommand(
SET_JITTER, newJitter - curJitter);
309 if (newThreshold >= 0)
313 newThreshold - curThreshold);
318 if (m_FirmwareVersion >= 3 && newPulseWidth >= 0)
321 rc_pulsewidth &= setRelativeCommand(
SET_PULSE_WITDH, (newPulseWidth - curPulseWidth) / 100.0);
325 if (rc_speed && rc_jitter && rc_threshold && rc_pulsewidth)
341 void XAGYLWheel::initOffset()
348 snprintf(offsetName,
MAXINDINAME,
"OFFSET_%d", i + 1);
349 snprintf(offsetLabel,
MAXINDINAME,
"#%d Offset", i + 1);
350 IUFillNumber(OffsetN + i, offsetName, offsetLabel,
"%.f", -9, 9, 1, 0);
361 bool XAGYLWheel::setMaximumSpeed(
int value)
363 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
364 snprintf(
cmd, DRIVER_LEN,
"S%X", value / 10);
365 return sendCommand(
cmd, res);
374 bool XAGYLWheel::setRelativeCommand(SET_COMMAND command,
int shift)
379 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
383 snprintf(
cmd, DRIVER_LEN,
"%s0", shift > 0 ?
"]" :
"[");
387 snprintf(
cmd, DRIVER_LEN,
"%s0", shift > 0 ?
"}" :
"{");
391 snprintf(
cmd, DRIVER_LEN,
"%s0", shift > 0 ?
"M" :
"N");
398 for (
int i = 0; i < std::abs(shift); ++i)
400 if (!sendCommand(
cmd, res))
422 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
423 snprintf(
cmd, DRIVER_LEN,
"G%X", f);
424 if (!sendCommand(
cmd, res))
428 char opt[DRIVER_LEN] = {0};
429 if (!receiveResponse(opt,
true))
432 if (!getFilterPosition())
444 bool XAGYLWheel::getStartupData()
446 bool rc1 = getFirmwareInfo();
448 bool rc2 = getSettingInfo();
450 for (
int i = 0; i < OffsetNP.
nnp; i++)
459 bool XAGYLWheel::getFirmwareInfo()
461 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
465 if (!sendCommand(
cmd, res))
467 IUSaveText(&FirmwareInfoT[FIRMWARE_PRODUCT], res);
471 if (!sendCommand(
cmd, res))
473 IUSaveText(&FirmwareInfoT[FIRMWARE_VERSION], res);
477 if (!sendCommand(
cmd, res))
479 IUSaveText(&FirmwareInfoT[FIRMWARE_SERIAL], res);
487 bool XAGYLWheel::getSettingInfo()
489 bool rc1 = getMaximumSpeed();
490 bool rc2 = getJitter();
491 bool rc3 = getThreshold();
494 if (m_FirmwareVersion >= 3)
495 rc4 = getPulseWidth();
497 return (rc1 && rc2 && rc3 && rc4);
503 bool XAGYLWheel::getFilterPosition()
505 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
507 if (!sendCommand(
cmd, res))
524 bool XAGYLWheel::getMaximumSpeed()
526 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
528 if (!sendCommand(
cmd, res))
532 int rc = sscanf(res,
"MaxSpeed %d%%", &maxSpeed);
544 bool XAGYLWheel::getJitter()
546 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
548 if (!sendCommand(
cmd, res))
552 int rc = sscanf(res,
"Jitter %d", &jitter);
565 bool XAGYLWheel::getThreshold()
567 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
569 if (!sendCommand(
cmd, res))
573 int rc = sscanf(res,
"Threshold %d", &threshold);
586 bool XAGYLWheel::getPulseWidth()
588 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
590 if (!sendCommand(
cmd, res))
594 int rc = sscanf(res,
"PulseWidth %duS", &pulseWidth);
607 bool XAGYLWheel::getMaxFilterSlots()
609 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
611 if (!sendCommand(
cmd, res))
614 int maxFilterSlots = 0;
615 int rc = sscanf(res,
"FilterSlots %d", &maxFilterSlots);
642 bool XAGYLWheel::reset(
int command)
644 char cmd[DRIVER_LEN] = {0}, resbuf[DRIVER_LEN] = {0};
648 if (command == COMMAND_PERFORM_CALIBRAITON)
654 snprintf(
cmd, DRIVER_LEN,
"R%d", value);
655 if (!sendCommand(
cmd, res))
659 if (command == COMMAND_REBOOT || command == COMMAND_INIT)
663 if (!receiveResponse(res))
666 while (0 != strcmp(res,
"P1"));
683 bool XAGYLWheel::setOffset(
int filter,
int shift)
688 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
689 snprintf(
cmd, DRIVER_LEN,
"%s0", shift > 0 ?
"(" :
")");
692 for (
int i = 0; i < std::abs(shift); ++i)
695 if (!sendCommand(
cmd, res))
700 int filter_num = 0, offset = 0;
701 int rc = sscanf(res,
"P%d Offset %d", &filter_num, &offset);
705 OffsetN[filter_num - 1].value = offset;
715 bool XAGYLWheel::getOffset(
int filter)
717 char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
718 snprintf(
cmd, DRIVER_LEN,
"O%d", filter + 1);
719 if (!sendCommand(
cmd, res))
722 int filter_num = 0, offset = 0;
723 int rc = sscanf(res,
"P%d Offset %d", &filter_num, &offset);
727 OffsetN[filter_num - 1].value = offset;
742 if (OffsetN !=
nullptr)
751 bool XAGYLWheel::receiveResponse(
char * res,
bool optional)
753 int nbytes_read = 0, rc = -1;
755 int timeout = optional ? OPTIONAL_TIMEOUT : DRIVER_TIMEOUT;
757 timeout, &nbytes_read);
773 assert(nbytes_read > 1);
774 res[nbytes_read - 2] = 0;
777 if (0 == strncmp(res,
"ERROR", 5))
792 bool XAGYLWheel::sendCommand(
const char *
cmd,
char * res)
794 int nbytes_written = 0, rc = -1;
796 tcflush(
PortFD, TCIOFLUSH);
806 LOGF_ERROR(
"Serial write error: %s.", errstr);
814 return receiveResponse(res);
820 void XAGYLWheel::hexDump(
char * buf,
const char * data,
int size)
822 for (
int i = 0; i < size; i++)
823 sprintf(buf + 3 * i,
"%02X ",
static_cast<uint8_t
>(data[i]));
826 buf[3 * size - 1] =
'\0';
const char * getDeviceName() const
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
void SelectFilterDone(int newpos)
The child class calls this function when the hardware successfully finished selecting a new filter wh...
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
void setFilterConnection(const uint8_t &value)
setFilterConnection Set Filter connection mode. Child class should call this in the constructor befor...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
int PortFD
For Serial & TCP connections.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
bool Handshake() override
perform handshake with device to check communication
virtual ~XAGYLWheel() override
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
bool SelectFilter(int) override
Select a new filter position.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
const char * getDefaultName() override
const char * FILTER_TAB
FILTER_TAB Where all the properties for filter wheels are located.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Implementations for common driver routines.
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
#define LOGF_WARN(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
@ value
the parser finished reading a JSON value