1 /*******************************************************************************
2 Copyright(c) 2016 Radek Kaczorek <rkaczorek AT gmail DOT com>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7 .
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12 .
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17 *******************************************************************************/
18
19 #include "quantum_wheel.h"
20
21 #include "connectionplugins/connectionserial.h"
22
23 #include <memory>
24 #include <cstring>
25 #include <termios.h>
26 #include <unistd.h>
27
28 #include "indicom.h"
29
30 #define VERSION_MAJOR 0
31 #define VERSION_MINOR 3
32
33 #define QUANTUM_TIMEOUT 5
34
35 std::unique_ptr<QFW> qfw(new QFW());
36
QFW()37 QFW::QFW()
38 {
39 setDeviceName(QFW::getDefaultName());
40 setVersion(VERSION_MAJOR, VERSION_MINOR);
41 setFilterConnection(CONNECTION_SERIAL | CONNECTION_TCP);
42 }
43
debugTriggered(bool enable)44 void QFW::debugTriggered(bool enable)
45 {
46 INDI_UNUSED(enable);
47 }
48
simulationTriggered(bool enable)49 void QFW::simulationTriggered(bool enable)
50 {
51 INDI_UNUSED(enable);
52 }
53
getDefaultName()54 const char *QFW::getDefaultName()
55 {
56 return (const char *)"Quantum Wheel";
57 }
58
Handshake()59 bool QFW::Handshake()
60 {
61 if (isSimulation())
62 {
63 IDMessage(getDeviceName(), "Simulation: connected");
64 PortFD = 1;
65 return true;
66 }
67 // check serial connection
68 if (PortFD < 0 || isatty(PortFD) == 0)
69 {
70 IDMessage(getDeviceName(), "Device /dev/ttyACM0 is not available\n");
71 return false;
72 }
73 // read description
74 char cmd[10] = {"SN\r\n"};
75 char resp[255]={0};
76 if (send_command(PortFD, cmd, resp) < 2)
77 return false;
78
79 // SN should respond SN<number>, this identifies a Quantum wheel
80 return strncmp(cmd, resp, 2) == 0;
81 }
82
initProperties()83 bool QFW::initProperties()
84 {
85 INDI::FilterWheel::initProperties();
86 addDebugControl();
87 addSimulationControl();
88
89 serialConnection->setDefaultPort("/dev/ttyACM0");
90
91 FilterSlotN[0].min = 1;
92 FilterSlotN[0].max = 7;
93 CurrentFilter = 1;
94
95 return true;
96 }
97
98 //bool QFW::updateProperties()
99 //{
100 // INDI::FilterWheel::updateProperties();
101
102 // if (isConnected())
103 // {
104 // // read number of filters
105 // char cmd[10] = {"EN\r\n"};
106 // char resp[255]={0};
107 // if (send_command(PortFD, cmd, resp) < 2)
108 // return false;
109 // int numFilters = resp[1] - '0';
110 // //FilterNameTP->ntp = numFilters;
111 // for (int i = 0; i < numFilters; i++)
112 // {
113 // sprintf(cmd, "F%1d\r\n", i);
114 // if (send_command(PortFD, cmd, resp) < 3)
115 // return false;
116 // char name[64];
117 // int n = strlen(resp);
118 // strncpy(name, &resp[2], n - 4);
119 // name[n] = 0;
120 // IUFillText(&FilterNameT[i], name, name, name);
121 // }
122 // }
123
124 // return true;
125 //}
126
ISGetProperties(const char * dev)127 void QFW::ISGetProperties(const char *dev)
128 {
129 INDI::FilterWheel::ISGetProperties(dev);
130 }
131
QueryFilter()132 int QFW::QueryFilter()
133 {
134 return CurrentFilter;
135 }
136
SelectFilter(int position)137 bool QFW::SelectFilter(int position)
138 {
139 // count from 0 to 6 for positions 1 to 7
140 position = position - 1;
141
142 if (position < 0 || position > 6)
143 return false;
144
145 if (isSimulation())
146 {
147 CurrentFilter = position + 1;
148 SelectFilterDone(CurrentFilter);
149 return true;
150 }
151
152 // goto
153 char targetpos[255]={0};
154 char curpos[255]={0};
155 char dmp[255];
156 int err;
157 int nbytes;
158
159 // format target position G[0-6]
160 sprintf(targetpos, "G%d\r\n ", position);
161
162 // write command
163 //int len = strlen(targetpos);
164
165 err = tty_write_string(PortFD, targetpos, &nbytes);
166 if (err)
167 {
168 char errmsg[255];
169 tty_error_msg(err, errmsg, MAXRBUF);
170 LOGF_ERROR("Serial write error: %s", errmsg);
171 return false;
172 }
173 //res = write(PortFD, targetpos, len);
174 dump(dmp, targetpos);
175 LOGF_DEBUG("CMD: %s", dmp);
176
177 // format target marker P[0-6]
178 sprintf(targetpos, "P%d", position);
179
180 // check current position
181 do
182 {
183 usleep(100 * 1000);
184 //res = read(PortFD, curpos, 255);
185 err = tty_read_section(PortFD, curpos, '\n', QUANTUM_TIMEOUT, &nbytes);
186 if (err)
187 {
188 char errmsg[255];
189 tty_error_msg(err, errmsg, MAXRBUF);
190 LOGF_ERROR("Serial read error: %s", errmsg);
191 return false;
192 }
193 curpos[nbytes] = 0;
194 dump(dmp, curpos);
195 LOGF_DEBUG("REP: %s", dmp);
196 } while (strncmp(targetpos, curpos, 2) != 0);
197
198 // return current position to indi
199 CurrentFilter = position + 1;
200 SelectFilterDone(CurrentFilter);
201 LOGF_DEBUG("CurrentFilter set to %d", CurrentFilter);
202
203 return true;
204 }
205
dump(char * buf,const char * data)206 void QFW::dump(char *buf, const char *data)
207 {
208 int i = 0;
209 int n = 0;
210 while(data[i] != 0)
211 {
212 if (isprint(data[i]))
213 {
214 buf[n] = data[i];
215 n++;
216 }
217 else
218 {
219 sprintf(buf + n, "[%02X]", data[i]);
220 n+=4;
221 }
222 i++;
223 }
224 }
225
226 // Send a command to the mount. Return the number of bytes received or 0 if
227 // case of error
228 // commands are null terminated, replies end with /n
send_command(int fd,const char * cmd,char * resp)229 int QFW::send_command(int fd, const char* cmd, char *resp)
230 {
231 int err;
232 int nbytes = 0;
233 char errmsg[MAXRBUF];
234 int cmd_len = strlen(cmd);
235 char dmp[255];
236
237 dump(dmp, cmd);
238 LOGF_DEBUG("CMD <%s>", dmp);
239
240 tcflush(fd, TCIOFLUSH);
241 if ((err = tty_write(fd, cmd, cmd_len, &nbytes)) != TTY_OK)
242 {
243 tty_error_msg(err, errmsg, MAXRBUF);
244 LOGF_ERROR("Serial write error: %s", errmsg);
245 return 0;
246 }
247
248 err = tty_read_section(fd, resp, '\n', QUANTUM_TIMEOUT, &nbytes);
249 if (err)
250 {
251 tty_error_msg(err, errmsg, MAXRBUF);
252 LOGF_ERROR("Serial read error: %s", errmsg);
253 return 0;
254 }
255
256 resp[nbytes] = 0;
257 dump(dmp, resp);
258 LOGF_DEBUG("RES <%s>", dmp);
259 return nbytes;
260 }
261
262