1 /*
2     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include <basedevice.h>
8 #include "indifocuser.h"
9 #include "clientmanager.h"
10 
11 namespace ISD
12 {
13 
registerProperty(INDI::Property prop)14 void Focuser::registerProperty(INDI::Property prop)
15 {
16     if (!prop.getRegistered())
17         return;
18 
19     if (prop.isNameMatch("FOCUS_MAX"))
20     {
21         auto nvp = prop.getNumber();
22         m_maxPosition = nvp->at(0)->getValue();
23     }
24 
25     DeviceDecorator::registerProperty(prop);
26 }
27 
processLight(ILightVectorProperty * lvp)28 void Focuser::processLight(ILightVectorProperty *lvp)
29 {
30     DeviceDecorator::processLight(lvp);
31 }
32 
processNumber(INumberVectorProperty * nvp)33 void Focuser::processNumber(INumberVectorProperty *nvp)
34 {
35     if (!strcmp(nvp->name, "FOCUS_MAX"))
36     {
37         m_maxPosition = nvp->np[0].value;
38     }
39 
40     DeviceDecorator::processNumber(nvp);
41 }
42 
processSwitch(ISwitchVectorProperty * svp)43 void Focuser::processSwitch(ISwitchVectorProperty *svp)
44 {
45     DeviceDecorator::processSwitch(svp);
46 }
47 
processText(ITextVectorProperty * tvp)48 void Focuser::processText(ITextVectorProperty *tvp)
49 {
50     DeviceDecorator::processText(tvp);
51 }
52 
focusIn()53 bool Focuser::focusIn()
54 {
55     auto focusProp = baseDevice->getSwitch("FOCUS_MOTION");
56 
57     if (!focusProp)
58         return false;
59 
60     auto inFocus = focusProp->findWidgetByName("FOCUS_INWARD");
61 
62     if (!inFocus)
63         return false;
64 
65     if (inFocus->getState() == ISS_ON)
66         return true;
67 
68     focusProp->reset();
69     inFocus->setState(ISS_ON);
70 
71     clientManager->sendNewSwitch(focusProp);
72 
73     return true;
74 }
75 
stop()76 bool Focuser::stop()
77 {
78     auto focusStop = baseDevice->getSwitch("FOCUS_ABORT_MOTION");
79 
80     if (!focusStop)
81         return false;
82 
83     focusStop->at(0)->setState(ISS_ON);
84     clientManager->sendNewSwitch(focusStop);
85 
86     return true;
87 }
88 
focusOut()89 bool Focuser::focusOut()
90 {
91     auto focusProp = baseDevice->getSwitch("FOCUS_MOTION");
92 
93     if (!focusProp)
94         return false;
95 
96     auto outFocus = focusProp->findWidgetByName("FOCUS_OUTWARD");
97 
98     if (!outFocus)
99         return false;
100 
101     if (outFocus->getState() == ISS_ON)
102         return true;
103 
104     focusProp->reset();
105     outFocus->setState(ISS_ON);
106 
107     clientManager->sendNewSwitch(focusProp);
108 
109     return true;
110 }
111 
getFocusDirection(ISD::Focuser::FocusDirection * dir)112 bool Focuser::getFocusDirection(ISD::Focuser::FocusDirection *dir)
113 {
114     auto focusProp = baseDevice->getSwitch("FOCUS_MOTION");
115 
116     if (!focusProp)
117         return false;
118 
119     auto inFocus = focusProp->findWidgetByName("FOCUS_INWARD");
120 
121     if (!inFocus)
122         return false;
123 
124     if (inFocus->getState() == ISS_ON)
125         *dir = FOCUS_INWARD;
126     else
127         *dir = FOCUS_OUTWARD;
128 
129     return true;
130 }
131 
moveByTimer(int msecs)132 bool Focuser::moveByTimer(int msecs)
133 {
134     auto focusProp = baseDevice->getNumber("FOCUS_TIMER");
135 
136     if (!focusProp)
137         return false;
138 
139     focusProp->at(0)->setValue(msecs);
140 
141     clientManager->sendNewNumber(focusProp);
142 
143     return true;
144 }
145 
moveAbs(int steps)146 bool Focuser::moveAbs(int steps)
147 {
148     auto focusProp = baseDevice->getNumber("ABS_FOCUS_POSITION");
149 
150     if (!focusProp)
151         return false;
152 
153     focusProp->at(0)->setValue(steps);
154 
155     clientManager->sendNewNumber(focusProp);
156 
157     return true;
158 }
159 
canAbsMove()160 bool Focuser::canAbsMove()
161 {
162     auto focusProp = baseDevice->getNumber("ABS_FOCUS_POSITION");
163 
164     if (!focusProp)
165         return false;
166     else
167         return true;
168 }
169 
moveRel(int steps)170 bool Focuser::moveRel(int steps)
171 {
172     INDI::PropertyView<INumber> *focusProp;
173 
174     if(canManualFocusDriveMove())
175     {
176         focusProp = baseDevice->getNumber("manualfocusdrive");
177 
178         FocusDirection dir;
179         getFocusDirection(&dir);
180         if (dir == FOCUS_INWARD)
181             steps = -abs(steps);
182         else if (dir == FOCUS_OUTWARD)
183             steps = abs(steps);
184 
185         //manualfocusdrive needs different steps value ​​at every turn
186         if (steps == getLastManualFocusDriveValue())
187             steps += 1;
188 
189         //Nikon Z6 fails if step is -1, 0, 1
190         if (deviation == NIKONZ6)
191         {
192             if (abs(steps) < 2)
193                 steps = 2;
194         }
195     }
196     else
197     {
198         focusProp = baseDevice->getNumber("REL_FOCUS_POSITION");
199     }
200 
201     if (!focusProp)
202         return false;
203 
204     focusProp->at(0)->setValue(steps);
205 
206     clientManager->sendNewNumber(focusProp);
207 
208     return true;
209 }
210 
canRelMove()211 bool Focuser::canRelMove()
212 {
213     auto focusProp = baseDevice->getNumber("REL_FOCUS_POSITION");
214 
215     if (!focusProp)
216         return false;
217     else
218         return true;
219 }
220 
canManualFocusDriveMove()221 bool Focuser::canManualFocusDriveMove()
222 {
223     auto focusProp = baseDevice->getNumber("manualfocusdrive");
224 
225     if (!focusProp)
226         return false;
227     else
228         return true;
229 }
230 
getLastManualFocusDriveValue()231 double Focuser::getLastManualFocusDriveValue()
232 {
233     auto focusProp = baseDevice->getNumber("manualfocusdrive");
234 
235     if (!focusProp)
236         return 0;
237 
238     return (double)focusProp->at(0)->getValue();
239 }
240 
241 
canTimerMove()242 bool Focuser::canTimerMove()
243 {
244     auto focusProp = baseDevice->getNumber("FOCUS_TIMER");
245 
246     if (!focusProp)
247         return false;
248     else
249         return true;
250 }
251 
setmaxPosition(uint32_t steps)252 bool Focuser::setmaxPosition(uint32_t steps)
253 {
254     auto focusProp = baseDevice->getNumber("FOCUS_MAX");
255 
256     if (!focusProp)
257         return false;
258 
259     focusProp->at(0)->setValue(steps);
260     clientManager->sendNewNumber(focusProp);
261 
262     return true;
263 }
264 
hasBacklash()265 bool Focuser::hasBacklash()
266 {
267     auto focusProp = baseDevice->getNumber("FOCUS_BACKLASH_STEPS");
268     return (focusProp != nullptr);
269 }
270 
setBacklash(int32_t steps)271 bool Focuser::setBacklash(int32_t steps)
272 {
273     auto focusToggle = baseDevice->getSwitch("FOCUS_BACKLASH_TOGGLE");
274     if (!focusToggle)
275         return false;
276 
277     // Make sure focus compensation is enabled.
278     if (steps != 0 && focusToggle->at(0)->getState() != ISS_ON)
279     {
280         focusToggle->reset();
281         focusToggle->at(0)->setState(ISS_ON);
282         focusToggle->at(1)->setState(ISS_OFF);
283         clientManager->sendNewSwitch(focusToggle);
284     }
285 
286     auto focusProp = baseDevice->getNumber("FOCUS_BACKLASH_STEPS");
287     if (!focusProp)
288         return false;
289 
290     focusProp->at(0)->setValue(steps);
291     clientManager->sendNewNumber(focusProp);
292 
293     // If steps = 0, disable compensation
294     if (steps == 0 && focusToggle->at(0)->getState() == ISS_ON)
295     {
296         focusToggle->reset();
297         focusToggle->at(0)->setState(ISS_OFF);
298         focusToggle->at(1)->setState(ISS_ON);
299         clientManager->sendNewSwitch(focusToggle);
300     }
301     return true;
302 }
303 
getBacklash()304 int32_t Focuser::getBacklash()
305 {
306     auto focusProp = baseDevice->getNumber("FOCUS_BACKLASH_STEPS");
307     if (!focusProp)
308         return -1;
309 
310     return focusProp->at(0)->getValue();
311 }
312 
hasDeviation()313 bool Focuser::hasDeviation()
314 {
315     if (getDeviceName() == "Nikon DSLR Z6")
316     {
317         deviation = NIKONZ6;
318         return true;
319     }
320     return false;
321 }
322 
323 }
324