Instrument Neutral Distributed Interface INDI 2.2.5
nframe.cpp
Go to the documentation of this file.
1/*
2 nFrameRotator Rotator
3
4 nFrame added by Gene N
5 Modified from indi_nstep_focuser
6
7 Copyright(c) 2019 Jasem Mutlaq. All rights reserved.
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22*/
23
24#include "nframe.h"
25
26#include "indicom.h"
27
28#include <cstring>
29#include <termios.h>
30#include <memory>
31#include <thread>
32#include <chrono>
33
34static std::unique_ptr<nFrameRotator> rotator(new nFrameRotator());
35
36
44
46{
48
49
50
51 // Stepping Modes
52 SteppingModeSP[STEPPING_WAVE].fill("STEPPING_WAVE", "Wave", ISS_OFF);
53 SteppingModeSP[STEPPING_HALF].fill( "STEPPING_HALF", "Half", ISS_OFF);
54 SteppingModeSP[STEPPING_FULL].fill( "STEPPING_FULL", "Full", ISS_ON);
55 SteppingModeSP.fill(getDeviceName(), "STEPPING_MODE", "Mode",
56 STEPPING_TAB, IP_RW, ISR_1OFMANY, 0, IPS_OK);
57
58 // Stepping Phase
59 SteppingPhaseNP[0].fill("PHASES", "Wiring", "%.f", 0, 2, 1, 0);
60 SteppingPhaseNP.fill(getDeviceName(), "STEPPING_PHASE", "Phase",
61 STEPPING_TAB, IP_RW, 0, IPS_OK);
62
63
64 RotatorSpeedNP[0].fill("ROTATE_SPEED_VALUE", "Step Rate", "%3.0f", 0.0, 255.0, 1.0, 255.0);
65 RotatorSpeedNP.fill(getDeviceName(), "ROTATE_SPEED", "Speed", MAIN_CONTROL_TAB, IP_RW, 0,
66 IPS_OK);
67
68 // Max Speed
69 MaxSpeedNP[0].fill("RATE", "Rate", "%.f", 1, 254, 10, 0);
70 MaxSpeedNP.fill(getDeviceName(), "MAX_SPEED", "Max Speed", MAIN_CONTROL_TAB, IP_RW, 0,
71 IPS_OK);
72
73 // Coil Energized Status
74 CoilStatusSP[COIL_ENERGIZED_OFF].fill("COIL_ENERGIZED_OFF", "De-energized", ISS_OFF);
75 CoilStatusSP[COIL_ENERGIZED_ON].fill("COIL_ENERGIZED_ON", "Energized", ISS_OFF);
76 // IUFillSwitch(&CoilStatusS[COIL_ENERGIZED_ON], "COIL_ENERGIZED_OFF", "Energized", ISS_OFF);
77 CoilStatusSP.fill(getDeviceName(), "COIL_MODE", "Coil After Move",
79 SettingNP[PARAM_STEPS_DEGREE].fill("PARAM_STEPS_DEGREE", "Steps/Degree", "%.2f", 1., 10000., 500., 1000.);
80 SettingNP.fill(getDeviceName(), "ROTATOR_SETTINGS", "Parameters", SETTINGS_TAB, IP_RW, 0,
81 IPS_OK);
82 // Rotator Ticks
83 RotatorAbsPosNP[0].fill("ROTATOR_ABSOLUTE_POSITION", "Value", "%.f", 0., 1000000., 0., 0.);
84 RotatorAbsPosNP.fill(getDeviceName(), "ABS_ROTATOR_POSITION", "Steps", MAIN_CONTROL_TAB,
85 IP_RW, 0, IPS_IDLE );
86
87
89
90 // Set limits as per documentation
91 GotoRotatorNP[0].setMin(0);
92 GotoRotatorNP[0].setMax(999999);
93 GotoRotatorNP[0].setStep(1000);
94
95 RotatorSpeedNP[0].setMin(1);
96 RotatorSpeedNP[0].setMax(254);
97 RotatorSpeedNP[0].setStep(10);
98
99 return true;
100}
101
103{
104 return "nFrameRotator";
105}
106
108{
110
111 if (isConnected())
112 {
113 // Read these values before defining focuser interface properties
114 defineProperty(RotatorAbsPosNP);
115 defineProperty(SettingNP);
118 SettingNP.load();
119 readPosition();
120 readSpeedInfo();
121 RotatorAbsPosNP.apply();
123
124 PresetNP.load();
125
126 bool rc = getStartupValues();
127
128 // Settings
129 defineProperty(MaxSpeedNP);
130 defineProperty(SteppingModeSP);
131 defineProperty(SteppingPhaseNP);
132 defineProperty(CoilStatusSP);
133
134 if (rc)
135 LOG_INFO("nFrameRotator is ready.");
136 else
137 LOG_WARN("Failed to query startup values.");
138 }
139 else
140 {
141
142 deleteProperty(MaxSpeedNP);
143 deleteProperty(SteppingModeSP);
144 deleteProperty(SteppingPhaseNP);
145 deleteProperty(CoilStatusSP);
147 deleteProperty(RotatorAbsPosNP);
148 }
149
150 return true;
151}
152
154{
155 char cmd[NFRAME_LEN] = {0}, res[NFRAME_LEN] = {0};
156
157 // Ack
158 cmd[0] = 0x6;
159
160 bool rc = sendCommand(cmd, res, 1, 1);
161 if (rc == false)
162 return false;
163
164 return res[0] == 'S';
165}
166
167bool nFrameRotator::sendCommand(const char * cmd, char * res, int cmd_len, int res_len)
168{
169 int nbytes_written = 0, nbytes_read = 0, rc = -1;
170
171 tcflush(PortFD, TCIOFLUSH);
172
173 if (cmd_len > 0)
174 {
175 char hex_cmd[NFRAME_LEN * 3] = {0};
176 hexDump(hex_cmd, cmd, cmd_len);
177 LOGF_DEBUG("CMD <%s>", hex_cmd);
178 rc = tty_write(PortFD, cmd, cmd_len, &nbytes_written);
179 }
180 else
181 {
182 LOGF_DEBUG("CMD <%s>", cmd);
183 rc = tty_write_string(PortFD, cmd, &nbytes_written);
184 }
185
186 if (rc != TTY_OK)
187 {
188 char errstr[MAXRBUF] = {0};
189 tty_error_msg(rc, errstr, MAXRBUF);
190 LOGF_ERROR("Serial write error: %s.", errstr);
191 return false;
192 }
193
194 if (res == nullptr)
195 return true;
196
197 if (res_len > 0)
198 rc = tty_read(PortFD, res, res_len, NFRAME_TIMEOUT, &nbytes_read);
199 else
200 rc = tty_nread_section(PortFD, res, NFRAME_LEN, NFRAME_STOP_CHAR, NFRAME_TIMEOUT, &nbytes_read);
201
202 if (rc != TTY_OK)
203 {
204 char errstr[MAXRBUF] = {0};
205 tty_error_msg(rc, errstr, MAXRBUF);
206 LOGF_ERROR("Serial read error: %s.", errstr);
207 return false;
208 }
209
210 if (res_len > 0)
211 {
212 char hex_res[NFRAME_LEN * 3] = {0};
213 hexDump(hex_res, res, res_len);
214 LOGF_DEBUG("RES <%s>", hex_res);
215 }
216 else
217 {
218 LOGF_DEBUG("RES <%s>", res);
219 }
220
221 tcflush(PortFD, TCIOFLUSH);
222
223 return true;
224}
225
226void nFrameRotator::hexDump(char * buf, const char * data, int size)
227{
228 for (int i = 0; i < size; i++)
229 sprintf(buf + 3 * i, "%02X ", static_cast<uint8_t>(data[i]));
230
231 if (size > 0)
232 buf[3 * size - 1] = '\0';
233}
234
235bool nFrameRotator::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
236{
237 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
238 {
239
240 // Stepping Phase
241 if (SteppingPhaseNP.isNameMatch(name))
242 {
243 if (setSteppingPhase(static_cast<uint8_t>(values[0])))
244 {
245 SteppingPhaseNP.update(values, names, n);
246 SteppingPhaseNP.setState(IPS_OK);
247 }
248 else
249 SteppingPhaseNP.setState(IPS_ALERT);
250
251 SteppingPhaseNP.apply();
252 return true;
253 }
254
255 // Current speed
256
257 if (RotatorSpeedNP.isNameMatch(name))
258 {
259 if (SetRotatorSpeed(static_cast<uint8_t>(values[0])))
260 {
261 RotatorSpeedNP.update(values, names, n);
263 }
264 else
265 {
267 }
268
270 return true;
271 }
272
273 // Max Speed
274 if (MaxSpeedNP.isNameMatch(name))
275 {
276 if (setMaxSpeed(static_cast<uint8_t>(values[0])))
277 {
278 MaxSpeedNP.update(values, names, n);
279 MaxSpeedNP.setState(IPS_OK);
280
281 // We must update the Min/Max of focus speed
282 RotatorSpeedNP[0].setMax(values[0]);
284 }
285 else
286 {
287 MaxSpeedNP.setState(IPS_ALERT);
288 }
289
290 MaxSpeedNP.apply();
291 return true;
292 }
293 if (SettingNP.isNameMatch(name))
294 {
295 bool rc = true;
296 std::vector<double> prevValue(SettingNP.count());
297 for (uint8_t i = 0; i < SettingNP.count(); i++)
298 prevValue[i] = SettingNP[i].getValue();
299 SettingNP.update(values, names, n);
300
301
302 if (SettingNP[PARAM_STEPS_DEGREE].value != prevValue[PARAM_STEPS_DEGREE])
303 {
304 GotoRotatorNP[0].setValue(calculateAngle(RotatorAbsPosNP[0].getValue()));
306 }
307
308 if (!rc)
309 {
310 for (uint8_t i = 0; i < SettingNP.count(); i++)
311 SettingNP[i].setValue(prevValue[i]);
312 }
313
314 SettingNP.setState(rc ? IPS_OK : IPS_ALERT);
315 SettingNP.apply();
316 return true;
317 }
318
319 }
320
321 return INDI::Rotator::ISNewNumber(dev, name, values, names, n);
322}
323
324bool nFrameRotator::ISNewSwitch(const char * dev, const char * name, ISState * states, char * names[], int n)
325{
326 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
327 {
328
329 // Stepping Mode
330 if (SteppingModeSP.isNameMatch(name))
331 {
332 SteppingModeSP.update(states, names, n);
333 SteppingModeSP.setState(IPS_OK);
334 SteppingModeSP.apply();
335 return true;
336 }
337
338 // Coil Status after Move is done
339 if (CoilStatusSP.isNameMatch(name))
340 {
341 int prevIndex = CoilStatusSP.findOnSwitchIndex();
342 LOGF_DEBUG("SETCOIL PINDEX=%d", prevIndex);
343 CoilStatusSP.update(states, names, n);
344 int state = CoilStatusSP.findOnSwitchIndex();
345 if (setCoilStatus(state))
346 {
347 CoilStatusSP.setState(IPS_OK);
348 if (state == COIL_ENERGIZED_ON)
349 LOG_WARN("Coil shall be kept energized after motion is complete. Watch for motor heating!");
350 else
351 LOG_INFO("Coil shall be de-energized after motion is complete.");
352 }
353 else
354 {
355 CoilStatusSP.reset();
356 CoilStatusSP[prevIndex].setState(ISS_ON);
357 CoilStatusSP.setState(IPS_ALERT);
358 LOG_ERROR("Failed to update coil energization status.");
359 }
360
361 CoilStatusSP.apply();
362 return true;
363 }
364 }
365
366 return INDI::Rotator::ISNewSwitch(dev, name, states, names, n);
367}
368
369bool nFrameRotator::getStartupValues()
370{
371 bool rc1 = readCoilStatus();
372 bool rc2 = readSteppingInfo();
373
374 return (rc1 && rc2 );
375}
376
378{
379 requestedAngle = angle ;
380
381 LOGF_DEBUG("Angle = <%f> Step/Deg=<%d>", angle, (int)SettingNP[PARAM_STEPS_DEGREE].getValue());
382 // Find closest distance
383 double r = (angle > 180) ? 360 - angle : angle;
384 int sign = (angle >= 0 && angle <= 180) ? 1 : -1;
385 sign = 1;
386 r = angle;
387
388 r *= sign;
390
391 double newTarget = r * SettingNP[PARAM_STEPS_DEGREE].getValue() + m_ZeroPosition;
392 m_TargetDiff = (int)newTarget - (int)RotatorAbsPosNP[0].getValue();
393 return IPS_BUSY;
394}
395
396
398{
399 if(m_TargetDiff > 0)
400 {
401 m_TargetDiff = 1;
402 wantAbort = true;
403 return false;
404 }
405 return true;
406}
407
409{
410 if (isConnected() == false)
411 return;
412
413 readPosition();
414
415 // Check if we have a pending motion
416 // and if we STOPPED, then let's take the next action
417 if ( ((RotatorAbsPosNP.getState() == IPS_BUSY || GotoRotatorNP.getState() == IPS_BUSY) && isMoving() == false) || wantAbort == true)
418 {
419 LOGF_DEBUG("wantAbort = %d, diff = %d", wantAbort, m_TargetDiff);
420 // Are we done moving?
421 if (m_TargetDiff == 0)
422 {
423 RotatorAbsPosNP.setState(IPS_OK);
425 LOGF_DEBUG("HIT reqAngle=%f diff=%d", requestedAngle, m_TargetDiff);
426 RotatorAbsPosNP.apply();
427 wantAbort = false;
428 }
429 else
430 {
431 // 999 is the max we can go in one command
432 // so we need to go 999 or LESS
433 // therefore for larger movements, we break it down.
434 int nextMotion = (std::abs(m_TargetDiff) > 999) ? 999 : std::abs(m_TargetDiff);
435 int direction = m_TargetDiff > 0 ? ROTATE_OUTWARD : ROTATE_INWARD;
436 int mode = SteppingModeSP.findOnSwitchIndex();
437 char cmd[NFRAME_LEN] = {0};
438 snprintf(cmd, NFRAME_LEN, ":F%d%d%03d#", direction, mode, nextMotion);
439 if (sendCommand(cmd) == false)
440 {
441 LOG_ERROR("Failed to issue motion command.");
443 {
446 }
447 if (RotatorAbsPosNP.getState() == IPS_BUSY)
448 {
449 RotatorAbsPosNP.setState(IPS_ALERT);
450 RotatorAbsPosNP.apply();
451 }
452 }
453 else
454 {
455 // Reduce target diff depending on the motion direction
456 // Negative targetDiff increases eventually to zero
457 // Positive targetDiff decreases eventually to zero
458 m_TargetDiff = m_TargetDiff + (nextMotion * ((direction == ROTATE_INWARD) ? 1 : -1));
459 }
460 }
461 // Check if can update the absolute position in case it changed.
462 }
463 if (m_TargetDiff == 0)
464 {
465 RotatorAbsPosNP.apply();
466 }
467 RotatorAbsPosNP.apply();
469
471}
472
473bool nFrameRotator::isMoving()
474{
475 char res[NFRAME_LEN] = {0};
476
477 bool rc = sendCommand("S", res, 1, 1);
478
479 if (rc && res[0] == '1')
480 return true;
481
482 return false;
483}
484
485
486bool nFrameRotator::readPosition()
487{
488 char res[NFRAME_LEN] = {0};
489
490 if (sendCommand(":RP", res, 3, 7) == false)
491 return false;
492
493 int32_t pos = 1e6;
494 sscanf(res, "%d", &pos);
495
496 if (pos == 1e6)
497 return false;
498 // LOGF_DEBUG("readPosFBPNB=< %d >", pos);
499
500 RotatorAbsPosNP[0].setValue(pos);
501 // if(m_TargetDiff != 0)
502 GotoRotatorNP[0].setValue(calculateAngle(RotatorAbsPosNP[0].getValue() ));
503 RotatorAbsPosNP.apply();
505
506 return true;
507}
508
509
510bool nFrameRotator::readSpeedInfo()
511{
512 char res[NFRAME_LEN] = {0};
513 int32_t max_step = 1e6, current_step = 1e6;
514
515 // Max Step
516 if (sendCommand(":RS", res, 3, 3) == false)
517 return false;
518 sscanf(res, "%d", &max_step);
519 if (max_step == 1e6)
520 return false;
521
522 // Current Step
523 if (sendCommand(":RO", res, 3, 3) == false)
524 return false;
525 sscanf(res, "%d", &current_step);
526 if (current_step == 1e6)
527 return false;
528
529 MaxSpeedNP[0].setValue(254 - max_step + 1);
530 MaxSpeedNP.setState(IPS_OK);
531
532 // nStep defines speed step rates from 1 to 254
533 // when 1 being the fastest, so for speed we flip the values
534 RotatorSpeedNP[0].setMax(254 - max_step + 1);
535 RotatorSpeedNP[0].setValue(254 - current_step + 1);
538 LOGF_DEBUG("Speed= %f cs=%d", RotatorSpeedNP[0].getValue(), current_step);
539
540 return true;
541}
542
543bool nFrameRotator::readSteppingInfo()
544{
545 char res[NFRAME_LEN] = {0};
546
547 if (sendCommand(":RW", res, 3, 1) == false)
548 return false;
549
550 int32_t phase = 1e6;
551 sscanf(res, "%d", &phase);
552
553 if (phase == 1e6)
554 return false;
555
556 SteppingPhaseNP[0].setValue(phase);
557 SteppingPhaseNP.setState(IPS_OK);
558
559 return true;
560}
561
562bool nFrameRotator::readCoilStatus()
563{
564 char res[NFRAME_LEN] = {0};
565
566 if (sendCommand(":RC", res, 3, 1) == false)
567 return false;
568
569 CoilStatusSP.reset();
570 LOGF_DEBUG("Coil status = %c", res[0]);
571
572 CoilStatusSP[COIL_ENERGIZED_OFF].setState((res[0] == '0') ? ISS_OFF : ISS_ON);
573 CoilStatusSP[COIL_ENERGIZED_ON].setState((res[0] == '0') ? ISS_ON : ISS_OFF);
574 CoilStatusSP.setState(IPS_OK);
575
576 return true;
577}
578
580{
581 // double min = range360(SettingN[PARAM_MIN_LIMIT].value);
582 // double max = range360(SettingN[PARAM_MAX_LIMIT].value);
583 // Clamp to range
584 // angle = std::max(min, std::min(max, angle));
585
586 // Find closest distance
587 double r = (angle > 180) ? 360 - angle : angle;
588 int sign = (angle >= 0 && angle <= 180) ? 1 : -1;
589
590 r *= sign;
592 double newTarget = r * SettingNP[PARAM_STEPS_DEGREE].getValue() + m_ZeroPosition;
593
594 char cmd[NFRAME_LEN] = {0};
595 snprintf(cmd, NFRAME_LEN, "#:CP+%06d#", (int)newTarget);
596 return sendCommand(cmd);
597}
598
600{
601 // Speed and Current nFrameRotator steps are opposite.
602 // Speed 1 is slowest, translated to 254 for nStep.
603 char cmd[NFRAME_LEN] = {0};
604 snprintf(cmd, NFRAME_LEN, "#:CO%03d#", 254 - speed + 1);
605 return sendCommand(cmd);
606}
607
608bool nFrameRotator::setMaxSpeed(uint8_t maxSpeed)
609{
610 // INDI Rotate Speed and Current nFrameRotator steps are opposite.
611 // INDI Speed 1 is slowest, translated to 254 for nFrame.
612 // and vice versa
613 char cmd[NFRAME_LEN] = {0};
614 snprintf(cmd, NFRAME_LEN, ":CS%03d#", 254 - maxSpeed + 1);
615 return sendCommand(cmd);
616}
617
618
619
620bool nFrameRotator::setSteppingPhase(uint8_t phase)
621{
622 char cmd[NFRAME_LEN] = {0};
623 snprintf(cmd, NFRAME_LEN, "#:CW%01d#", phase);
624 return sendCommand(cmd);
625}
626
627bool nFrameRotator::setCoilStatus(uint8_t status)
628{
629 char cmd[NFRAME_LEN] = {0};
630 snprintf(cmd, NFRAME_LEN, "#:CC%01d#", status == COIL_ENERGIZED_OFF ? 1 : 0);
631 LOGF_DEBUG("setCoil = %d hex=%x", status, status);
632 LOGF_DEBUG("setCoilS = %s CEOFF=%d CEON = %d", cmd, COIL_ENERGIZED_OFF, COIL_ENERGIZED_ON);
633 return sendCommand(cmd);
634}
635
637{
639
640 SteppingModeSP.save(fp);
641 SettingNP.save(fp);
642
643
644 return true;
645}
646double nFrameRotator::calculateAngle(uint32_t steps)
647{
648 int diff = (static_cast<int32_t>(steps) - m_ZeroPosition) *
650 // LOGF_DEBUG("RANGE=%f",(int)(range360((float(diff)+0.5) / SettingN[PARAM_STEPS_DEGREE].value)*100)/100.);
651 return range360((float(diff) + 0.5) / SettingNP[PARAM_STEPS_DEGREE].getValue());
652 // return (int)(range360((float(diff)+0.5) / SettingN[PARAM_STEPS_DEGREE].value)*100)/100.;
653}
654
655/*
656bool nFrameRotator::setSpeedRange(uint32_t min, uint32_t max)
657{
658 return true;
659}
660*/
661
663{
665
666 SettingNP.load();
667}
668
bool isConnected() const
int setValue(const INDI::LilXmlElement &root, char *errmsg)
handle SetXXX commands from client
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.
void defineProperty(INumberVectorProperty *property)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
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)
void SetCapability(uint32_t cap)
SetRotatorCapability sets the Rotator capabilities. All capabilities must be initialized.
INDI::PropertySwitch ReverseRotatorSP
INDI::PropertyNumber GotoRotatorNP
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
INDI::PropertyNumber PresetNP
Definition indirotator.h:92
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the reverse direction property in the configuration file
@ ROTATE_OUTWARD
Definition nframe.h:36
@ ROTATE_INWARD
Definition nframe.h:35
virtual bool SyncRotator(double angle) override
SyncRotator Set current angle as the supplied angle without moving the rotator.
Definition nframe.cpp:579
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition nframe.cpp:107
virtual IPState MoveRotator(double angle) override
MoveRotator Go to specific angle.
Definition nframe.cpp:377
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the reverse direction property in the configuration file
Definition nframe.cpp:636
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition nframe.cpp:408
virtual bool Handshake() override
perform handshake with device to check communication
Definition nframe.cpp:153
INDI::PropertyNumber RotatorSpeedNP
Definition nframe.h:63
bool SetRotatorSpeed(uint8_t speed)
Definition nframe.cpp:599
const char * getDefaultName() override
Definition nframe.cpp:102
virtual bool AbortRotator() override
AbortRotator Abort all motion.
Definition nframe.cpp:397
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition nframe.cpp:324
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition nframe.cpp:662
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition nframe.cpp:235
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
Definition nframe.cpp:45
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
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_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
double range360(double r)
range360 Limits an angle to be between 0-360 degrees.
Definition indicom.c:1321
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 LOG_WARN(txt)
Definition indilogger.h:73
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition indilogger.h:72
#define LOGF_ERROR(fmt,...)
Definition indilogger.h:80
#define LOG_INFO(txt)
Definition indilogger.h:74
#define getDeviceName
uint8_t cmd[4]
Definition pwc-ioctl.h:2