Instrument Neutral Distributed Interface INDI  2.0.2
pegasus_indigo.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2022 Jasem Mutlaq. All rights reserved.
3 
4  Pegasus INDIGO Filter Wheel
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the Free
8  Software Foundation; either version 2 of the License, or (at your option)
9  any later version.
10 
11  This program is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 
21  The full GNU General Public License is included in this distribution in the
22  file called LICENSE.
23 *******************************************************************************/
24 
25 #include "pegasus_indigo.h"
26 #include "indicom.h"
27 
28 #include <cmath>
29 #include <memory>
30 #include <regex>
31 #include <termios.h>
32 #include <cstring>
33 #include <sys/ioctl.h>
34 #include <chrono>
35 #include <math.h>
36 #include <iomanip>
37 
38 static std::unique_ptr<PegasusINDIGO> falcon(new PegasusINDIGO());
39 
41 {
42  setVersion(1, 0);
44 }
45 
47 {
49 
51 
55  // Firmware
56  FirmwareTP[0].fill("VERSION", "Version", "NA");
57  FirmwareTP.fill(getDeviceName(), "FIRMWARE_INFO", "Firmware", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
58 
59  CurrentFilter = 1;
60  FilterSlotN[0].min = 1;
61  FilterSlotN[0].max = 7;
62 
63  return true;
64 }
65 
67 {
69 
70  if (isConnected())
71  {
72  // Main Control
73  getFirmware();
74  defineProperty(FirmwareTP);
75  }
76  else
77  {
78  // Main Control
79  deleteProperty(FirmwareTP);
80  }
81 
82  return true;
83 }
84 
86 {
87  return "Pegasus INDIGO";
88 }
89 
94 {
95  char res[DRIVER_LEN] = {0};
96  if (sendCommand("W#", res))
97  {
98  return strstr(res, "FW_OK");
99  }
100 
101  return false;
102 }
103 
107 bool PegasusINDIGO::getFirmware()
108 {
109  char res[DRIVER_LEN] = {0};
110  if (sendCommand("WV", res))
111  {
112  FirmwareTP[0].setText(res + 3);
113  return true;
114  }
115 
116  return false;
117 }
118 
122 bool PegasusINDIGO::SelectFilter(int position)
123 {
124  TargetFilter = position;
125  char command[DRIVER_LEN] = {0}, response[DRIVER_LEN] = {0};
126  snprintf(command, DRIVER_LEN, "WM:%d", position);
127  return sendCommand(command, response);
128 }
129 
134 {
135  if (isConnected() && FilterSlotNP.s == IPS_BUSY)
136  {
137  char response[DRIVER_LEN] = {0};
138  if (sendCommand("WF", response))
139  {
140  int position = -1;
141  if (sscanf(response, "WF:%d", &position) == 1)
142  {
143  if (position == TargetFilter)
144  SelectFilterDone(position);
145  }
146  }
147  }
148 
150 }
151 
155 bool PegasusINDIGO::sendCommand(const char * cmd, char * res, int cmd_len, int res_len)
156 {
157  int nbytes_written = 0, nbytes_read = 0, rc = -1;
158 
159  tcflush(PortFD, TCIOFLUSH);
160 
161  if (cmd_len > 0)
162  {
163  char hex_cmd[DRIVER_LEN * 3] = {0};
164  hexDump(hex_cmd, cmd, cmd_len);
165  LOGF_DEBUG("CMD <%s>", hex_cmd);
166  rc = tty_write(PortFD, cmd, cmd_len, &nbytes_written);
167  }
168  else
169  {
170  LOGF_DEBUG("CMD <%s>", cmd);
171 
172  char formatted_command[DRIVER_LEN] = {0};
173  snprintf(formatted_command, DRIVER_LEN, "%s\n", cmd);
174  rc = tty_write_string(PortFD, formatted_command, &nbytes_written);
175  }
176 
177  if (rc != TTY_OK)
178  {
179  char errstr[MAXRBUF] = {0};
180  tty_error_msg(rc, errstr, MAXRBUF);
181  LOGF_ERROR("Serial write error: %s.", errstr);
182  return false;
183  }
184 
185  if (res == nullptr)
186  return true;
187 
188  if (res_len > 0)
189  rc = tty_read(PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
190  else
191  rc = tty_nread_section(PortFD, res, DRIVER_LEN, DRIVER_STOP_CHAR, DRIVER_TIMEOUT, &nbytes_read);
192 
193  if (rc != TTY_OK)
194  {
195  char errstr[MAXRBUF] = {0};
196  tty_error_msg(rc, errstr, MAXRBUF);
197  LOGF_ERROR("Serial read error: %s.", errstr);
198  return false;
199  }
200 
201  if (res_len > 0)
202  {
203  char hex_res[DRIVER_LEN * 3] = {0};
204  hexDump(hex_res, res, res_len);
205  LOGF_DEBUG("RES <%s>", hex_res);
206  }
207  else
208  {
209  // Remove \r\n
210  res[nbytes_read - 2] = 0;
211  LOGF_DEBUG("RES <%s>", res);
212  }
213 
214  tcflush(PortFD, TCIOFLUSH);
215 
216  return true;
217 }
218 
222 void PegasusINDIGO::hexDump(char * buf, const char * data, uint32_t size)
223 {
224  for (uint32_t i = 0; i < size; i++)
225  sprintf(buf + 3 * i, "%02X ", static_cast<uint8_t>(data[i]));
226 
227  if (size > 0)
228  buf[3 * size - 1] = '\0';
229 }
230 
234 std::vector<std::string> PegasusINDIGO::split(const std::string &input, const std::string &regex)
235 {
236  // passing -1 as the submatch index parameter performs splitting
237  std::regex re(regex);
238  std::sregex_token_iterator
239  first{input.begin(), input.end(), re, -1},
240  last;
241  return {first, last};
242 }
243 
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
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.
uint32_t getPollingPeriod() const
getPollingPeriod Return the polling period.
void defineProperty(INumberVectorProperty *property)
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INumberVectorProperty FilterSlotNP
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 initProperties() override
Initilize properties initial state and value. The child class must implement this function.
void setFilterConnection(const uint8_t &value)
setFilterConnection Set Filter connection mode. Child class should call this in the constructor befor...
int PortFD
For Serial & TCP connections.
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool SelectFilter(int) override
Select a new filter position.
bool Handshake() override
perform handshake with device to check communication
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
const char * getDefaultName() override
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
@ IP_RO
Definition: indiapi.h:184
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_IDLE
Definition: indiapi.h:161
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition: indicom.c:424
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition: indicom.c:482
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:474
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1167
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
Definition: indicom.c:666
Implementations for common driver routines.
@ TTY_OK
Definition: indicom.h:150
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
#define MAXRBUF
Definition: indiserver.cpp:102
__u8 cmd[4]
Definition: pwc-ioctl.h:2