diff --git a/drivers/filter_wheel/ioptron_wheel.cpp b/drivers/filter_wheel/ioptron_wheel.cpp new file mode 100644 index 0000000000..08e60689ca --- /dev/null +++ b/drivers/filter_wheel/ioptron_wheel.cpp @@ -0,0 +1,333 @@ +/******************************************************************************* + Copyright(c) 2024 Joe Zhou. All rights reserved. + + iOptron Filter Wheel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*******************************************************************************/ + +#include "ioptron_wheel.h" + +#include "indicom.h" +#include +#include +#include +#include + +#define iEFW_TIMEOUT 4 + +/* +command : +:WMnn# Response: 1 +get position ,nn filter num。 + +:WP# Response: nn# or -1# +get curr position,nn =curr position,if is moving,return -1。 + +:WOnnsnnnnn# Response: 1 +set offset。nn =filter num , snnnnn=offset + +:WFnn# Response: snnnnn# +get offset 。nn = filter num , snnnnn=offset + +“:DeviceInfo#” Response: “nnnnnnnnnnnn#” +This command includes 12 digits. +The 7th and 8th digit means model of filter wheel. +Model number 99 is iEFW-15, 98 is iEFW18 + +:FW1# Response: nnnnnnnnnnnn# +get firmware version + + +*/ + + +static std::unique_ptr iefw_wheel(new iEFW()); + +iEFW::iEFW() +{ + setVersion(1, 0); + setFilterConnection(CONNECTION_SERIAL); +} + +const char *iEFW::getDefaultName() +{ + return "iOptron Wheel"; +} + +bool iEFW::initProperties() +{ + INDI::FilterWheel::initProperties(); + serialConnection->setDefaultPort("/dev/ttyUSB3"); + serialConnection->setDefaultBaudRate(Connection::Serial::B_115200); + FilterSlotN[0].min = 1; + FilterSlotN[0].max = 8; + // Firmware of the iEFW + IUFillText(&FirmwareT[0], "FIRMWARE", "Firmware", "Unknown"); + IUFillTextVector(&FirmwareTP, FirmwareT, 1, getDeviceName(), "FIRMWARE_ID", "iEFW Firmware", FILTER_TAB, IP_RO, 60, IPS_IDLE); + IUFillText(&WheelIDT[0], "MODEL", "Model", "iEFW"); + IUFillTextVector(&WheelIDTP, WheelIDT, 1, getDeviceName(), "MODEL_ID", "iEFW Model", FILTER_TAB, IP_RO, 60, IPS_IDLE); + return true; +} + +bool iEFW::updateProperties() +{ + INDI::FilterWheel::updateProperties(); + + if (isConnected()) + { + defineProperty(&HomeSP); + defineProperty(&FirmwareTP); + defineProperty(&WheelIDTP); + bool rc1=getiEFWInfo(); + bool rc2=getiEFWfirmwareInfo(); + getFilterPos(); + return (rc1 && rc2); + } + else + { + deleteProperty(HomeSP.name); + deleteProperty(FirmwareTP.name); + deleteProperty(WheelIDTP.name); + } + return true; +} + +bool iEFW::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) +{ + if (dev != nullptr && strcmp(dev, getDeviceName()) == 0) + { + if (!strcmp(HomeSP.name, name)) + { + if (getiEFWID()) + { + LOG_INFO("Filter getid."); + HomeSP.s = IPS_OK; + FilterSlotNP.s = IPS_OK; + IDSetNumber(&FilterSlotNP, nullptr); + } + else + HomeSP.s = IPS_ALERT; + IDSetSwitch(&HomeSP, nullptr); + return true; + } + } + + return INDI::FilterWheel::ISNewSwitch(dev, name, states, names, n); +} + +bool iEFW::Handshake() +{ + + return getiEFWID(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +bool iEFW::getiEFWInfo() +{ + int nbytes_written = 0, nbytes_read = 0, rc = -1; + char resp[16]; + int iefwpos, iefwmodel, iefwlast; + sleep(2); + tcflush(PortFD, TCIOFLUSH); + if ( (rc = tty_write(PortFD, ":DeviceInfo#", strlen(":DeviceInfo#"), &nbytes_written)) != TTY_OK) + { + char errstr[MAXRBUF] = {0}; + tty_error_msg(rc, errstr, MAXRBUF); + DEBUGF(INDI::Logger::DBG_ERROR, "Init send iEFW deviceinfo error: %s.", errstr); + return false; + }; + + if ( (rc = tty_read_section(PortFD, resp, '#', iEFW_TIMEOUT * 2, &nbytes_read)) != TTY_OK) + { + char errstr[MAXRBUF] = {0}; + tty_error_msg(rc, errstr, MAXRBUF); + DEBUGF(INDI::Logger::DBG_ERROR, "Init read iEFW deviceinfo error: %s.", errstr); + return false; + }; + tcflush(PortFD, TCIOFLUSH); + resp[nbytes_read] = '\0'; + sscanf(resp, "%6d%2d%4d", &iefwpos, &iefwmodel, &iefwlast); + if ((iefwmodel == 98)|| (iefwmodel == 99)) + { + if (iefwmodel==99) + { + FilterSlotN[0].max = 5; + WheelIDTP.s = IPS_OK; + IUSaveText(&WheelIDT[0], "iEFW-15"); + IDSetText(&WheelIDTP, "iEFW Model is %s", "iEFW-15"); + }; + if (iefwmodel==98) + { + FilterSlotN[0].max = 8; + WheelIDTP.s = IPS_OK; + IUSaveText(&WheelIDT[0], "iEFW-18"); + IDSetText(&WheelIDTP, "iEFW Model is %s", "iEFW-18"); + }; + return true; + } + else + { + DEBUGF(INDI::Logger::DBG_ERROR, "iEFW getinfo Response: %s", resp); + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////// +bool iEFW::getiEFWfirmwareInfo() +{ + int nbytes_written = 0, nbytes_read = 0, rc = -1; + char errstr[MAXRBUF]; + char resp[16] = {0}; + char iefwfirminfo[16] = {0}; + tcflush(PortFD, TCIOFLUSH); + if ( (rc = tty_write(PortFD, ":FW1#", 5, &nbytes_written)) != TTY_OK) + { + tty_error_msg(rc, errstr, MAXRBUF); + DEBUGF(INDI::Logger::DBG_ERROR, "get iEFW FiremwareInfo error: %s.", errstr); + } + if ( (rc = tty_read_section(PortFD, resp, '#', iEFW_TIMEOUT, &nbytes_read)) != TTY_OK) + { + tty_error_msg(rc, errstr, MAXRBUF); + DEBUGF(INDI::Logger::DBG_ERROR, "get iEFW FirmwareInfo error: %s.", errstr); + return false; + } + tcflush(PortFD, TCIOFLUSH); + resp[nbytes_read] = '\0'; + sscanf(resp, "%12s", iefwfirminfo); + FirmwareTP.s = IPS_OK; + IUSaveText(&FirmwareT[0], iefwfirminfo); + IDSetText(&FirmwareTP, "iEFW Firmware is %s", iefwfirminfo); + LOGF_DEBUG("Success, response from iEFW is : %s", iefwfirminfo); + return true; +} + +int iEFW::getFilterPos() +{ + int nbytes_written = 0, nbytes_read = 0, rc = -1; + char errstr[MAXRBUF]; + char resp[16] = {0}; +// char iefwposinfo[16] = {0}; + int iefwpos = 1; + tcflush(PortFD, TCIOFLUSH); + if ( (rc = tty_write(PortFD, ":WP#", 4, &nbytes_written)) != TTY_OK) + { + tty_error_msg(rc, errstr, MAXRBUF); + DEBUGF(INDI::Logger::DBG_ERROR, "send iEFW filter pos Info error: %s.", errstr); + } + if ( (rc = tty_read_section(PortFD, resp, '#', iEFW_TIMEOUT, &nbytes_read)) != TTY_OK) + { + tty_error_msg(rc, errstr, MAXRBUF); + DEBUGF(INDI::Logger::DBG_ERROR, "read iEFW filter pos Info error: %s.", errstr); + return false; + } + tcflush(PortFD, TCIOFLUSH); + resp[nbytes_read] = '\0'; + LOGF_DEBUG("Success, response from iEFW is : %s", resp); + rc=sscanf(resp, "%2d", &iefwpos); + if (rc > 0) + { + if (iefwpos>=0) + { + CurrentFilter=iefwpos+1; + FilterSlotN[0].value = CurrentFilter; + FilterSlotNP.s = IPS_OK; + return CurrentFilter; + } + else + return -1; + } + else + return 999; + +} + + +bool iEFW::getiEFWID() +{ + return getiEFWInfo(); +} +///////////////////////////////////////////////////////////////////////////// +/* +void iEFW::initOffset() +{ + +} + + +bool iEFW::setOffset(int filter, int shift) +{ + + return true; +} + +///////////////////////////////////////////////////////////////////////////// +bool iEFW::getOffset(int filter) +{ + return true; +} +*/ +///////////////////////////////////////////////////////////////////////////// + +bool iEFW::SelectFilter(int f) +{ + int nbytes_written = 0, rc = -1; + char errstr[MAXRBUF]; + // char resp[16] = {0}; + // char iefwposinfo[16] = {0}; + int iefwpos=-1; + char cmd[7]={0}; + if (CurrentFilter == f) + { + SelectFilterDone(CurrentFilter); + return true; + } + f = f - 1; + + if (f < 0 || f > (FilterSlotN[0].max-1)) + return false; + + tcflush(PortFD, TCIOFLUSH); + snprintf(cmd,7, ":WM0%d#", f); + if ( (rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK) + { + tty_error_msg(rc, errstr, MAXRBUF); + DEBUGF(INDI::Logger::DBG_ERROR, "select iEFW send pos Info error: %s.", errstr); + } + tcflush(PortFD, TCIOFLUSH); + // check current position -1 is moving + do + { + usleep(100 * 1000); + iefwpos=getFilterPos(); + } + while (iefwpos == -1); + // return current position to indi + CurrentFilter = f + 1; + SelectFilterDone(CurrentFilter); + FilterSlotNP.s = IPS_OK; + IDSetNumber(&FilterSlotNP, "Selected filter position reached"); + LOGF_DEBUG("CurrentFilter set to %d", CurrentFilter); + return true; +} + +int iEFW::QueryFilter() +{ + return CurrentFilter; +} + diff --git a/drivers/filter_wheel/ioptron_wheel.h b/drivers/filter_wheel/ioptron_wheel.h new file mode 100644 index 0000000000..86b102145e --- /dev/null +++ b/drivers/filter_wheel/ioptron_wheel.h @@ -0,0 +1,58 @@ +/******************************************************************************* + Copyright(c) 2024 Joe Zhou. All rights reserved. + + iOptron Filter Wheel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*******************************************************************************/ + +#pragma once + +#include "indifilterwheel.h" + +class iEFW : public INDI::FilterWheel +{ + public: + iEFW(); + virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; + + protected: + const char *getDefaultName() override; + bool initProperties() override; + bool updateProperties() override; + bool Handshake() override; + int QueryFilter() override; + bool SelectFilter(int) override; +// void TimerHit() override; + int getFilterPos(); + // Firmware of the iEFW + ITextVectorProperty FirmwareTP; + IText FirmwareT[1] {}; + // Filter Wheel ID + ITextVectorProperty WheelIDTP; + IText WheelIDT[1] {}; + + private: + + bool getiEFWID(); + bool getiEFWInfo(); + bool getiEFWfirmwareInfo(); + void initOffset(); + // Calibration offset + bool getOffset(int filter); + bool setOffset(int filter, int shift); + ISwitch HomeS[1]; + ISwitchVectorProperty HomeSP; +};