1 /*
2     SPDX-FileCopyrightText: 2017 Jasem Mutlaq <mutlaqja@ikarustech.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 
8 #include "rotatorsettings.h"
9 #include "Options.h"
10 #include "fov.h"
11 #include "kstarsdata.h"
12 
13 #include <indicom.h>
14 #include <basedevice.h>
15 #include <cmath>
16 
RotatorSettings(QWidget * parent)17 RotatorSettings::RotatorSettings(QWidget *parent) : QDialog(parent)
18 {
19     setupUi(this);
20 
21     rotatorGauge->setFormat("%v");
22     rotatorGauge->setMinimum(0);
23     rotatorGauge->setMaximum(360);
24 
25     connect(angleSlider, &QSlider::valueChanged, this, [this](int angle)
26     {
27         angleSpin->setValue(angle);
28     });
29 
30     connect(setAngleB, SIGNAL(clicked()), this, SLOT(gotoAngle()));
31 
32     PAMulSpin->setValue(Options::pAMultiplier());
33     PAOffsetSpin->setValue(Options::pAOffset());
34 
35     connect(setPAB, SIGNAL(clicked()), this, SLOT(setPA()));
36 
37     syncFOVPA->setChecked(Options::syncFOVPA());
38     connect(syncFOVPA, &QCheckBox::toggled, [this](bool toggled)
39     {
40         Options::setSyncFOVPA(toggled);
41         if (toggled) syncPA(targetPASpin->value());
42     });
43 
44     connect(enforceRotationCheck, SIGNAL(toggled(bool)), targetPASpin, SLOT(setEnabled(bool)));
45     connect(targetPASpin, SIGNAL(valueChanged(double)), this, SLOT(syncPA(double)));
46     connect(PAMulSpin, &QSpinBox::editingFinished, this, [this]()
47     {
48         Options::setPAMultiplier(PAMulSpin->value());
49         updatePA();
50     }
51            );
52     connect(PAOffsetSpin, &QSpinBox::editingFinished, this, [this]()
53     {
54         Options::setPAOffset(PAOffsetSpin->value());
55         updatePA();
56     });
57 }
58 
setRotator(ISD::GDInterface * rotator)59 void RotatorSettings::setRotator(ISD::GDInterface *rotator)
60 {
61     currentRotator = rotator;
62 
63     connect(currentRotator, &ISD::GDInterface::propertyDefined, [&](INDI::Property * prop)
64     {
65         if (prop->isNameMatch("ABS_ROTATOR_ANGLE"))
66         {
67             auto absAngle = prop->getNumber();
68             setCurrentAngle(absAngle->at(0)->getValue());
69         }
70     });
71 }
72 
73 
gotoAngle()74 void RotatorSettings::gotoAngle()
75 {
76     double angle = angleSpin->value();
77     currentRotator->runCommand(INDI_SET_ROTATOR_ANGLE, &angle);
78 }
79 
setCurrentAngle(double angle)80 void RotatorSettings::setCurrentAngle(double angle)
81 {
82     angleEdit->setText(QString::number(angle, 'f', 3));
83     rawAngle->setText(QString::number(angle, 'f', 3));
84     rotatorGauge->setValue(angle);
85     updatePA();
86 }
87 
updatePA()88 void RotatorSettings::updatePA()
89 {
90     double PA = rotatorGauge->value() * PAMulSpin->value() + PAOffsetSpin->value();
91     // Limit PA to -180 to +180
92     if (PA > 180)
93         PA -= 360;
94     if (PA < -180)
95         PA += 360;
96 
97     //PASpin->setValue(PA);
98     PAOut->setText(QString::number(PA, 'f', 3));
99 }
100 
refresh()101 void RotatorSettings::refresh()
102 {
103     PAMulSpin->setValue(Options::pAMultiplier());
104     PAOffsetSpin->setValue(Options::pAOffset());
105     updatePA();
106 }
107 
syncPA(double PA)108 void RotatorSettings::syncPA(double PA)
109 {
110     if (syncFOVPA->isChecked())
111     {
112         for (auto oneFOV : KStarsData::Instance()->getTransientFOVs())
113         {
114             // Only change the PA for the sensor FOV
115             if (oneFOV->objectName() == "sensor_fov")
116             {
117                 // Make sure that it is always displayed
118                 if (!Options::showSensorFOV())
119                 {
120                     Options::setShowSensorFOV(true);
121                     oneFOV->setProperty("visible", true);
122                 }
123 
124                 // JM 2020-10-15
125                 // While we have the correct Position Angle
126                 // Because Ekos reads frame TOP-BOTTOM instead of the BOTTOM-TOP approach
127                 // used by astrometry, the PA is always 180 degree off. To avoid confusion to the user
128                 // the PA is drawn REVERSED to show the *expected* frame. However, the final PA is
129                 // the "correct" PA as expected by astrometry.
130                 double drawnPA = PA >= 0 ? (PA - 180) : (PA + 180);
131                 oneFOV->setPA(drawnPA);
132                 break;
133             }
134         }
135     }
136 }
137 
setPA()138 void RotatorSettings::setPA()
139 {
140     // PA = RawAngle * Multiplier + Offset
141     double rawAngle = (PASpin->value() - PAOffsetSpin->value()) / PAMulSpin->value();
142     // Get raw angle (0 to 360) from PA (-180 to +180)
143     if (rawAngle < 0)
144         rawAngle += 360;
145     else if (rawAngle > 360)
146         rawAngle -= 360;
147 
148     //angleEdit->setText(QString::number(rawAngle, 'f', 3));
149     angleSpin->setValue(rawAngle);
150     gotoAngle();
151 }
152