Instrument Neutral Distributed Interface INDI 2.2.5
lacerta_mfoc.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2018 Franck Le Rhun. All rights reserved.
3 Copyright(c) 2018 Christian Liska. All rights reserved.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8 .
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13 .
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*******************************************************************************/
19
20#include "lacerta_mfoc.h"
21#include "indicom.h"
23
24#include <cmath>
25#include <memory>
26#include <cstring>
27#include <unistd.h>
28
29// We declare an auto pointer to lacerta_mfoc.
30static std::unique_ptr<lacerta_mfoc> Lacerta_mfoc(new lacerta_mfoc());
31
32// Delay for receiving messages
33#define FOCUSMFOC_TIMEOUT 1000
34// According to documentation for v2
35#define MFOC_POSMAX_HARDWARE 250000
36#define MFOC_POSMIN_HARDWARE 300
37
38/************************************************************************************
39 *
40************************************************************************************/
45
46/************************************************************************************
47 *
48************************************************************************************/
50{
51 return "Lacerta MFOC";
52}
53
54/************************************************************************************
55 *
56************************************************************************************/
57void lacerta_mfoc::ISGetProperties(const char *dev)
58{
59 if (dev != nullptr && strcmp(dev, getDeviceName()) != 0)
60 return;
61
63
64 defineProperty(TempTrackDirSP);
65 TempTrackDirSP.load();
66
67 defineProperty(StartSavedPositionSP);
68 StartSavedPositionSP.load();
69}
70
71/************************************************************************************
72 *
73************************************************************************************/
75{
77
78 FocusBacklashNP[0].setMin(0);
79 FocusBacklashNP[0].setMax(255);
80 FocusBacklashNP[0].setStep(1);
81 FocusBacklashNP[0].setValue(12);
82
83 // IUFillNumber(&BacklashN[0], "BACKLASH", "step", "%4.2f", 0, 255, 1, 12);
84 // IUFillNumberVector(&BacklashNP, BacklashN, 1, getDeviceName(), "BACKLASH_SETTINGS", "Backlash", MAIN_CONTROL_TAB, IP_RW, 60,
85 // IPS_IDLE);
86
87 TempCompNP[0].fill("TEMPCOMP", "step/10 degC", "%4.2f", -5000, 5000, 1, 65);
88 TempCompNP.fill(getDeviceName(), "TEMPCOMP_SETTINGS", "T Comp.", MAIN_CONTROL_TAB, IP_RW, 60,
89 IPS_IDLE);
90
93 FocusMaxPosNP[0].setStep((FocusMaxPosNP[0].getMax() - FocusMaxPosNP[0].getMin()) / 20.0);
94 FocusMaxPosNP[0].setValue(110000);
95
96 FocusAbsPosNP[0].setMin(0);
97 FocusAbsPosNP[0].setMax(FocusMaxPosNP[0].getValue());
98 FocusAbsPosNP[0].setStep(FocusAbsPosNP[0].getMax() / 50.0);
99
100 TempTrackDirSP[MODE_TDIR_BOTH].fill("Both", "Both", ISS_ON);
101 TempTrackDirSP[MODE_TDIR_IN].fill("In", "In", ISS_ON);
102 TempTrackDirSP[MODE_TDIR_OUT].fill("Out", "Out", ISS_ON);
103 TempTrackDirSP.fill(getDeviceName(), "Temp. dir.", "Temp. dir.",
105 ISR_1OFMANY, 60, IPS_IDLE);
106
107 StartSavedPositionSP[MODE_SAVED_ON].fill("Yes", "Yes", ISS_ON);
108 StartSavedPositionSP[MODE_SAVED_OFF].fill("No", "No", ISS_OFF);
109 StartSavedPositionSP.fill(getDeviceName(), "Start saved pos.",
110 "Start saved pos.", MAIN_CONTROL_TAB, IP_RW,
111 ISR_1OFMANY, 60, IPS_IDLE);
112
113 return true;
114}
115
116/************************************************************************************
117 *
118************************************************************************************/
120{
121 // Get Initial Position before we define it in the INDI::Focuser class
122 FocusAbsPosNP[0].setValue(GetAbsFocuserPosition());
123
125
126 if (isConnected())
127 {
128 //defineProperty(&BacklashNP);
129 defineProperty(TempCompNP);
130 defineProperty(TempTrackDirSP);
131 defineProperty(StartSavedPositionSP);
132
133 }
134 else
135 {
136 //deleteProperty(BacklashNP.name);
137 deleteProperty(TempCompNP);
138 deleteProperty(TempTrackDirSP);
139 deleteProperty(StartSavedPositionSP);
140 }
141
142 return true;
143}
144
145/************************************************************************************
146 *
147************************************************************************************/
149{
150 char MFOC_cmd[32] = ": Q #";
151 char MFOC_res[32] = {0};
152 char MFOC_res_type[32] = "0";
153 int MFOC_pos_measd = 0;
154 int nbytes_written = 0;
155 int nbytes_read = 0;
156
157
158 tty_write_string(PortFD, MFOC_cmd, &nbytes_written);
159 LOGF_DEBUG("CMD <%s>", MFOC_cmd);
160 tty_read_section(PortFD, MFOC_res, 0xD, FOCUSMFOC_TIMEOUT, &nbytes_read);
161 LOGF_DEBUG("RES <%s>", MFOC_res_type);
162
163 sscanf(MFOC_res, "%s %d", MFOC_res_type, &MFOC_pos_measd);
164
165 if (MFOC_res_type[0] == 'P')
166 {
167 FocusAbsPosNP[0].setValue(MFOC_pos_measd);
169 return true;
170 }
171
172 return false;
173}
174
175/************************************************************************************
176 *
177************************************************************************************/
178bool lacerta_mfoc::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
179{
180 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
181 {
182 // Temp. Track Direction
183 if (TempTrackDirSP.isNameMatch(name))
184 {
185 TempTrackDirSP.update(states, names, n);
186 int tdir = 0;
187 int index = TempTrackDirSP.findOnSwitchIndex();
188 char MFOC_cmd[32] = ": I ";
189 char MFOC_res[32] = {0};
190 int nbytes_read = 0;
191 int nbytes_written = 0;
192 int MFOC_tdir_measd = 0;
193 char MFOC_res_type[32] = "0";
194
195 switch (index)
196 {
197 case MODE_TDIR_BOTH:
198 tdir = 0;
199 strcat(MFOC_cmd, "0 #");
200 break;
201
202 case MODE_TDIR_IN:
203 tdir = 1;
204 strcat(MFOC_cmd, "1 #");
205 break;
206
207 case MODE_TDIR_OUT:
208 tdir = 2;
209 strcat(MFOC_cmd, "2 #");
210 break;
211
212 default:
213 TempTrackDirSP.setState(IPS_ALERT);
214 LOGF_ERROR("Unknown mode index %d", index);
215 return true;
216 }
217
218
219 tty_write_string(PortFD, MFOC_cmd, &nbytes_written);
220 LOGF_DEBUG("CMD <%s>", MFOC_cmd);
221 tty_write_string(PortFD, ": W #", &nbytes_written);
222 tty_read_section(PortFD, MFOC_res, 0xD, FOCUSMFOC_TIMEOUT, &nbytes_read);
223 sscanf (MFOC_res, "%s %d", MFOC_res_type, &MFOC_tdir_measd);
224 LOGF_DEBUG("RES <%s>", MFOC_res);
225
226 if (MFOC_tdir_measd == tdir)
227 {
228 TempTrackDirSP.setState(IPS_OK);
229 }
230 else
231 {
232 TempTrackDirSP.setState(IPS_ALERT);
233 }
234
235 TempTrackDirSP.apply();
236 return true;
237 }
238
239
240 // Start at saved position
241 if (StartSavedPositionSP.isNameMatch(name))
242 {
243 StartSavedPositionSP.update(states, names, n);
244 int svstart = 0;
245 int index = StartSavedPositionSP.findOnSwitchIndex();
246 char MFOC_cmd[32] = ": F ";
247 char MFOC_res[32] = {0};
248 int nbytes_read = 0;
249 int nbytes_written = 0;
250 int MFOC_svstart_measd = 0;
251 char MFOC_res_type[32] = "0";
252
253 switch (index)
254 {
255 case MODE_SAVED_ON:
256 svstart = 1;
257 strcat(MFOC_cmd, "1 #");
258 break;
259
260 case MODE_SAVED_OFF:
261 svstart = 0;
262 strcat(MFOC_cmd, "0 #");
263 break;
264
265 default:
266 StartSavedPositionSP.setState(IPS_ALERT);
267 LOGF_ERROR("Unknown mode index %d", index);
268 return true;
269 }
270
271 tty_write_string(PortFD, MFOC_cmd, &nbytes_written);
272 LOGF_DEBUG("CMD <%s>", MFOC_cmd);
273 tty_write_string(PortFD, ": N #", &nbytes_written);
274 tty_read_section(PortFD, MFOC_res, 0xD, FOCUSMFOC_TIMEOUT, &nbytes_read);
275 sscanf (MFOC_res, "%s %d", MFOC_res_type, &MFOC_svstart_measd);
276
277 LOGF_DEBUG("RES <%s>", MFOC_res);
278 // LOGF_DEBUG("Debug MFOC cmd sent %s", MFOC_cmd);
279 if (MFOC_svstart_measd == svstart)
280 {
281 StartSavedPositionSP.setState(IPS_OK);
282 }
283 else
284 {
285 StartSavedPositionSP.setState(IPS_ALERT);
286 }
287
288 StartSavedPositionSP.apply();
289 return true;
290 }
291 }
292
293 return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
294}
295
296bool lacerta_mfoc::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
297{
298 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
299 {
300 // if (strcmp(name, "BACKLASH_SETTINGS") == 0)
301 // {
302 // return SetBacklash(values, names, n);
303 // }
304
305
306 if (strcmp(name, "TEMPCOMP_SETTINGS") == 0)
307 {
308 return SetTempComp(values, names, n);
309 }
310 }
311
312 // Let INDI::Focuser handle any other number properties
313 return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
314}
315
316/************************************************************************************
317 *
318************************************************************************************/
319//bool lacerta_mfoc::SetBacklash(double values[], char *names[], int n)
321{
322 LOGF_DEBUG("-> BACKLASH_SETTINGS", 0);
323 char MFOC_cmd[32] = ": B ";
324 char MFOC_res[32] = {0};
325 int nbytes_read = 0;
326 int nbytes_written = 0;
327 int MFOC_tdir_measd = 0;
328 //int bl_int = 0;
329 char bl_char[32] = {0};
330 char MFOC_res_type[32] = "0";
331 // BacklashNP.s = IPS_OK;
332 // IUUpdateNumber(&BacklashNP, values, names, n);
333 // bl_int = BacklashN[0].value;
334 sprintf(bl_char, "%d", steps);
335 strcat(bl_char, " #");
336 strcat(MFOC_cmd, bl_char);
337
338 tty_write_string(PortFD, MFOC_cmd, &nbytes_written);
339 LOGF_DEBUG("CMD <%s>", MFOC_cmd);
340 tty_write_string(PortFD, ": J #", &nbytes_written);
341
342 tty_read_section(PortFD, MFOC_res, 0xD, FOCUSMFOC_TIMEOUT, &nbytes_read);
343
344 sscanf (MFOC_res, "%s %d", MFOC_res_type, &MFOC_tdir_measd);
345
346 LOGF_DEBUG("RES <%s>", MFOC_res);
347
348 //IDSetNumber(&BacklashNP, nullptr);
349
350 return true;
351}
352
353bool lacerta_mfoc::SetTempComp(double values[], char *names[], int n)
354{
355 char MFOC_cmd[32] = ": D ";
356 char MFOC_res[32] = {0};
357 int nbytes_read = 0;
358 int nbytes_written = 0;
359 int MFOC_tc_measd = 0;
360 int tc_int = 0;
361 char tc_char[32] = {0};
362 char MFOC_res_type[32] = "0";
363 TempCompNP.setState(IPS_OK);
364 TempCompNP.update(values, names, n);
365 tc_int = TempCompNP[0].getValue();
366 sprintf(tc_char, "%d", tc_int);
367 strcat(tc_char, " #");
368 strcat(MFOC_cmd, tc_char);
369
370 tty_write_string(PortFD, MFOC_cmd, &nbytes_written);
371 LOGF_DEBUG("CMD <%s>", MFOC_cmd);
372 tty_write_string(PortFD, ": U #", &nbytes_written);
373
374 tty_read_section(PortFD, MFOC_res, 0xD, FOCUSMFOC_TIMEOUT, &nbytes_read);
375
376 sscanf (MFOC_res, "%s %d", MFOC_res_type, &MFOC_tc_measd);
377
378 LOGF_DEBUG("RES <%s>", MFOC_res);
379
380 TempCompNP.apply();
381
382 return true;
383}
384
386{
387 char MFOC_cmd[32] = ": G ";
388 char MFOC_res[32] = {0};
389 int nbytes_read = 0;
390 int nbytes_written = 0;
391 int MFOC_pm_measd = 0;
392 char pm_char[32] = {0};
393 char MFOC_res_type[32] = "0";
394
395 sprintf(pm_char, "%d", ticks);
396 strcat(pm_char, " #");
397 strcat(MFOC_cmd, pm_char);
398
399 tty_write_string(PortFD, MFOC_cmd, &nbytes_written);
400 LOGF_DEBUG("CMD <%s>", MFOC_cmd);
401 tty_write_string(PortFD, ": O #", &nbytes_written);
402
403 tty_read_section(PortFD, MFOC_res, 0xD, FOCUSMFOC_TIMEOUT, &nbytes_read);
404
405 sscanf (MFOC_res, "%s %d", MFOC_res_type, &MFOC_pm_measd);
406
407 LOGF_DEBUG("RES <%s>", MFOC_res);
408 return true;
409}
410
411/************************************************************************************
412 *
413************************************************************************************/
415{
416 char MFOC_cmd[32] = ": M ";
417 char abs_pos_char[32] = {0};
418 int nbytes_written = 0;
419
420 //int pos = GetAbsFocuserPosition();
421 sprintf(abs_pos_char, "%d", targetTicks);
422 strcat(abs_pos_char, " #");
423 strcat(MFOC_cmd, abs_pos_char);
424
425 tty_write_string(PortFD, MFOC_cmd, &nbytes_written);
426 LOGF_DEBUG("CMD <%s>", MFOC_cmd);
427 FocusAbsPosNP[0].setValue(targetTicks);
428
429 GetAbsFocuserPosition();
430 return IPS_OK;
431}
432
433/************************************************************************************
434 *
435************************************************************************************/
437{
438 // Calculation of the demand absolute position
439 auto targetTicks = FocusAbsPosNP[0].getValue();
440 if (dir == FOCUS_INWARD) targetTicks -= ticks;
441 else targetTicks += ticks;
442 targetTicks = std::clamp(targetTicks, FocusAbsPosNP[0].getMin(), FocusAbsPosNP[0].getMax());
443
446
447 return MoveAbsFocuser(targetTicks);
448}
449//Waiting makes no sense - will be immediately interrupted by the ekos system...
450//int ticks = std::abs((int)(targetTicks - pos) * FOCUS_MOTION_DELAY);
451//LOGF_INFO("sleep for %d ms", ticks);
452//usleep(ticks + 5000);
453
454
456{
457 // Save Focuser Config
459
460 // Save additional MFPC Config
461 //IUSaveConfigNumber(fp, &BacklashNP);
462 TempCompNP.save(fp);
463
464 return true;
465}
466
467uint32_t lacerta_mfoc::GetAbsFocuserPosition()
468{
469 char MFOC_cmd[32] = ": Q #";
470 char MFOC_res[32] = {0};
471 char MFOC_res_type[32] = "0";
472 int MFOC_pos_measd = 0;
473
474 int nbytes_written = 0;
475 int nbytes_read = 0;
476 int count = 0;
477
478 tty_write_string(PortFD, MFOC_cmd, &nbytes_written);
479 LOGF_DEBUG("CMD <%s>", MFOC_cmd);
480
481 do
482 {
483 tty_read_section(PortFD, MFOC_res, 0xD, FOCUSMFOC_TIMEOUT, &nbytes_read);
484 sscanf(MFOC_res, "%s %d", MFOC_res_type, &MFOC_pos_measd);
485 count++;
486 }
487 while(strcmp(MFOC_res_type, "P") != 0 && count < 100);
488
489 LOGF_DEBUG("RES <%s>", MFOC_res_type);
490 LOGF_DEBUG("current position: %d", MFOC_pos_measd);
491
492 return static_cast<uint32_t>(MFOC_pos_measd);
493}
bool isConnected() const
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 SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusBacklashNP
INDI::PropertyNumber FocusAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool saveConfigItems(FILE *fp) override
virtual void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool load()
load Attempt to load property values from configuration file.
void save(FILE *f) const
save Save property to configuration file.
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
const char * getDefaultName() override
void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
virtual bool saveConfigItems(FILE *fp) override
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ IP_RW
Definition indiapi.h:184
IPState
Property state.
Definition indiapi.h:158
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition indicom.c:653
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition indicom.c:473
Implementations for common driver routines.
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOGF_ERROR(fmt,...)
Definition indilogger.h:80
#define getDeviceName
#define MFOC_POSMAX_HARDWARE
#define FOCUSMFOC_TIMEOUT
#define MFOC_POSMIN_HARDWARE