Instrument Neutral Distributed Interface INDI 2.2.5
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
38static std::unique_ptr<PegasusINDIGO> falcon(new PegasusINDIGO());
39
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 FilterSlotNP[0].setMin(1);
61 FilterSlotNP[0].setMax(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
107bool 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
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{
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
155bool 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
222void 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
234std::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}
bool isConnected() const
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.
INDI::PropertyNumber 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
Initialize 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
Initialize 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:182
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_IDLE
Definition indiapi.h:159
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition indicom.c:418
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition indicom.c:548
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition indicom.c:473
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
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:759
Implementations for common driver routines.
@ TTY_OK
Definition indicom.h:54
#define MAXRBUF
Definition indidriver.c:52
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOGF_ERROR(fmt,...)
Definition indilogger.h:80
#define getDeviceName
uint8_t cmd[4]
Definition pwc-ioctl.h:2