1 | /*
|
---|
2 | LX200 Classoc
|
---|
3 | Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
|
---|
4 |
|
---|
5 | This library is free software; you can redistribute it and/or
|
---|
6 | modify it under the terms of the GNU Lesser General Public
|
---|
7 | License as published by the Free Software Foundation; either
|
---|
8 | version 2.1 of the License, or (at your option) any later version.
|
---|
9 |
|
---|
10 | This library is distributed in the hope that it will be useful,
|
---|
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
13 | Lesser General Public License for more details.
|
---|
14 |
|
---|
15 | You should have received a copy of the GNU Lesser General Public
|
---|
16 | License along with this library; if not, write to the Free Software
|
---|
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
18 |
|
---|
19 | */
|
---|
20 |
|
---|
21 | #include "lx200classic.h"
|
---|
22 | #include "lx200driver.h"
|
---|
23 |
|
---|
24 | #include <stdio.h>
|
---|
25 | #include <stdlib.h>
|
---|
26 | #include <string.h>
|
---|
27 |
|
---|
28 | extern LX200Generic *telescope;
|
---|
29 | extern INumberVectorProperty EquatorialCoordsWNP;
|
---|
30 | extern INumberVectorProperty EquatorialCoordsRNP;
|
---|
31 | extern ITextVectorProperty TimeTP;
|
---|
32 | extern int MaxReticleFlashRate;
|
---|
33 |
|
---|
34 | /* Handy Macros */
|
---|
35 | #define currentRA EquatorialCoordsRNP.np[0].value
|
---|
36 | #define currentDEC EquatorialCoordsRNP.np[1].value
|
---|
37 | #define targetRA EquatorialCoordsWNP.np[0].value
|
---|
38 | #define targetDEC EquatorialCoordsWNP.np[1].value
|
---|
39 |
|
---|
40 | #define BASIC_GROUP "Main Control"
|
---|
41 | #define LIBRARY_GROUP "Library"
|
---|
42 | #define MOVE_GROUP "Movement Control"
|
---|
43 |
|
---|
44 | static IText ObjectText[] = {{"objectText", "Info", 0, 0, 0, 0}};
|
---|
45 | static ITextVectorProperty ObjectInfoTP = {mydev, "Object Info", "", BASIC_GROUP, IP_RO, 0, IPS_IDLE, ObjectText, NARRAY(ObjectText), "", 0};
|
---|
46 |
|
---|
47 | /* Library group */
|
---|
48 | static ISwitch StarCatalogS[] = {{"STAR", "", ISS_ON, 0, 0}, {"SAO", "", ISS_OFF, 0, 0}, {"GCVS", "", ISS_OFF, 0, 0}};
|
---|
49 | static ISwitch DeepSkyCatalogS[] = {{"NGC", "", ISS_ON, 0, 0}, {"IC", "", ISS_OFF, 0, 0}, {"UGC", "", ISS_OFF, 0, 0}, {"Caldwell", "", ISS_OFF, 0, 0}, {"Arp", "", ISS_OFF, 0, 0}, {"Abell", "", ISS_OFF, 0, 0}, {"Messier", "", ISS_OFF, 0, 0}};
|
---|
50 | static ISwitch SolarS[] = { {"Select", "Select item...", ISS_ON, 0, 0}, {"1", "Mercury", ISS_OFF,0 , 0}, {"2", "Venus", ISS_OFF, 0, 0}, {"3", "Moon", ISS_OFF, 0, 0}, {"4", "Mars", ISS_OFF, 0, 0}, {"5", "Jupiter", ISS_OFF, 0, 0}, {"6", "Saturn", ISS_OFF, 0, 0}, {"7", "Uranus", ISS_OFF, 0, 0}, {"8", "Neptune", ISS_OFF, 0, 0}, {"9", "Pluto", ISS_OFF, 0 ,0}};
|
---|
51 |
|
---|
52 | static ISwitchVectorProperty StarCatalogSP = { mydev, "Star Catalogs", "", LIBRARY_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, StarCatalogS, NARRAY(StarCatalogS), "", 0};
|
---|
53 | static ISwitchVectorProperty DeepSkyCatalogSP= { mydev, "Deep Sky Catalogs", "", LIBRARY_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, DeepSkyCatalogS, NARRAY(DeepSkyCatalogS), "", 0};
|
---|
54 | static ISwitchVectorProperty SolarSP = { mydev, "SOLAR_SYSTEM", "Solar System", LIBRARY_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, SolarS, NARRAY(SolarS), "", 0};
|
---|
55 |
|
---|
56 | static INumber ObjectN[] = {{ "ObjectN", "Number", "%g", 1., 10000., 1., 0., 0, 0, 0}};
|
---|
57 | static INumberVectorProperty ObjectNoNP= { mydev, "Object Number", "", LIBRARY_GROUP, IP_RW, 0, IPS_IDLE, ObjectN, NARRAY(ObjectN), "", 0 };
|
---|
58 |
|
---|
59 | static INumber MaxSlew[] = {{"maxSlew", "Rate", "%g", 2.0, 9.0, 1.0, 9., 0, 0 ,0}};
|
---|
60 | static INumberVectorProperty MaxSlewRateNP = { mydev, "Max slew Rate", "", MOVE_GROUP, IP_RW, 0, IPS_IDLE, MaxSlew, NARRAY(MaxSlew), "", 0};
|
---|
61 |
|
---|
62 | static INumber altLimit[] = {
|
---|
63 | {"minAlt", "min Alt", "%+03f", -90., 90., 0., 0., 0, 0, 0},
|
---|
64 | {"maxAlt", "max Alt", "%+03f", -90., 90., 0., 0., 0, 0, 0}};
|
---|
65 | static INumberVectorProperty ElevationLimitNP = { mydev, "altLimit", "Slew elevation Limit", BASIC_GROUP, IP_RW, 0, IPS_IDLE, altLimit, NARRAY(altLimit), "", 0};
|
---|
66 |
|
---|
67 | void changeLX200ClassicDeviceName(const char *newName)
|
---|
68 | {
|
---|
69 | strcpy(ObjectInfoTP.device, newName);
|
---|
70 | strcpy(SolarSP.device, newName);
|
---|
71 | strcpy(StarCatalogSP.device, newName);
|
---|
72 | strcpy(DeepSkyCatalogSP.device, newName);
|
---|
73 | strcpy(ObjectNoNP.device, newName);
|
---|
74 | strcpy(MaxSlewRateNP.device , newName );
|
---|
75 | strcpy(ElevationLimitNP.device , newName );
|
---|
76 | }
|
---|
77 |
|
---|
78 | LX200Classic::LX200Classic() : LX200Generic()
|
---|
79 | {
|
---|
80 | ObjectInfoTP.tp[0].text = NULL;
|
---|
81 |
|
---|
82 | currentCatalog = LX200_STAR_C;
|
---|
83 | currentSubCatalog = 0;
|
---|
84 |
|
---|
85 | }
|
---|
86 |
|
---|
87 | void LX200Classic::ISGetProperties (const char *dev)
|
---|
88 | {
|
---|
89 |
|
---|
90 | if (dev && strcmp (thisDevice, dev))
|
---|
91 | return;
|
---|
92 |
|
---|
93 | LX200Generic::ISGetProperties(dev);
|
---|
94 |
|
---|
95 | IDDefNumber (&ElevationLimitNP, NULL);
|
---|
96 | IDDefText (&ObjectInfoTP, NULL);
|
---|
97 | IDDefSwitch (&SolarSP, NULL);
|
---|
98 | IDDefSwitch (&StarCatalogSP, NULL);
|
---|
99 | IDDefSwitch (&DeepSkyCatalogSP, NULL);
|
---|
100 | IDDefNumber (&ObjectNoNP, NULL);
|
---|
101 | IDDefNumber (&MaxSlewRateNP, NULL);
|
---|
102 |
|
---|
103 | }
|
---|
104 |
|
---|
105 | void LX200Classic::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
|
---|
106 | {
|
---|
107 | // ignore if not ours //
|
---|
108 | if (strcmp (dev, thisDevice))
|
---|
109 | return;
|
---|
110 |
|
---|
111 | LX200Generic::ISNewText (dev, name, texts, names, n);
|
---|
112 | }
|
---|
113 |
|
---|
114 |
|
---|
115 | void LX200Classic::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
|
---|
116 | {
|
---|
117 | int err=0;
|
---|
118 |
|
---|
119 | // ignore if not ours //
|
---|
120 | if (strcmp (dev, thisDevice))
|
---|
121 | return;
|
---|
122 |
|
---|
123 | if ( !strcmp (name, ObjectNoNP.name) )
|
---|
124 | {
|
---|
125 |
|
---|
126 | char object_name[256];
|
---|
127 |
|
---|
128 | if (checkPower(&ObjectNoNP))
|
---|
129 | return;
|
---|
130 |
|
---|
131 | if (selectCatalogObject(fd, currentCatalog, (int) values[0]) < 0)
|
---|
132 | {
|
---|
133 | ObjectNoNP.s = IPS_ALERT;
|
---|
134 | IDSetNumber(&ObjectNoNP, "Failed to select catalog object.");
|
---|
135 | return;
|
---|
136 | }
|
---|
137 |
|
---|
138 | getLX200RA(fd, &targetRA);
|
---|
139 | getLX200DEC(fd, &targetDEC);
|
---|
140 |
|
---|
141 | ObjectNoNP.s = IPS_OK;
|
---|
142 | IDSetNumber(&ObjectNoNP , "Object updated.");
|
---|
143 |
|
---|
144 | if (getObjectInfo(fd, object_name) < 0)
|
---|
145 | IDMessage(thisDevice, "Getting object info failed.");
|
---|
146 | else
|
---|
147 | {
|
---|
148 | IUSaveText(&ObjectInfoTP.tp[0], object_name);
|
---|
149 | IDSetText (&ObjectInfoTP, NULL);
|
---|
150 | }
|
---|
151 |
|
---|
152 | handleCoordSet();
|
---|
153 | return;
|
---|
154 | }
|
---|
155 |
|
---|
156 | if ( !strcmp (name, MaxSlewRateNP.name) )
|
---|
157 | {
|
---|
158 |
|
---|
159 | if (checkPower(&MaxSlewRateNP))
|
---|
160 | return;
|
---|
161 |
|
---|
162 | if ( ( err = setMaxSlewRate(fd, (int) values[0]) < 0) )
|
---|
163 | {
|
---|
164 | handleError(&MaxSlewRateNP, err, "Setting maximum slew rate");
|
---|
165 | return;
|
---|
166 | }
|
---|
167 | MaxSlewRateNP.s = IPS_OK;
|
---|
168 | MaxSlewRateNP.np[0].value = values[0];
|
---|
169 | IDSetNumber(&MaxSlewRateNP, NULL);
|
---|
170 | return;
|
---|
171 | }
|
---|
172 |
|
---|
173 |
|
---|
174 | if (!strcmp (name, ElevationLimitNP.name))
|
---|
175 | {
|
---|
176 | // new elevation limits
|
---|
177 | double minAlt = 0, maxAlt = 0;
|
---|
178 | int i, nset;
|
---|
179 |
|
---|
180 | if (checkPower(&ElevationLimitNP))
|
---|
181 | return;
|
---|
182 |
|
---|
183 | for (nset = i = 0; i < n; i++)
|
---|
184 | {
|
---|
185 | INumber *altp = IUFindNumber (&ElevationLimitNP, names[i]);
|
---|
186 | if (altp == &altLimit[0])
|
---|
187 | {
|
---|
188 | minAlt = values[i];
|
---|
189 | nset += minAlt >= -90.0 && minAlt <= 90.0;
|
---|
190 | } else if (altp == &altLimit[1])
|
---|
191 | {
|
---|
192 | maxAlt = values[i];
|
---|
193 | nset += maxAlt >= -90.0 && maxAlt <= 90.0;
|
---|
194 | }
|
---|
195 | }
|
---|
196 | if (nset == 2)
|
---|
197 | {
|
---|
198 | //char l[32], L[32];
|
---|
199 | if ( ( err = setMinElevationLimit(fd, (int) minAlt) < 0) )
|
---|
200 | {
|
---|
201 | handleError(&ElevationLimitNP, err, "Setting elevation limit");
|
---|
202 | }
|
---|
203 | setMaxElevationLimit(fd, (int) maxAlt);
|
---|
204 | ElevationLimitNP.np[0].value = minAlt;
|
---|
205 | ElevationLimitNP.np[1].value = maxAlt;
|
---|
206 | ElevationLimitNP.s = IPS_OK;
|
---|
207 | IDSetNumber (&ElevationLimitNP, NULL);
|
---|
208 | } else
|
---|
209 | {
|
---|
210 | ElevationLimitNP.s = IPS_IDLE;
|
---|
211 | IDSetNumber(&ElevationLimitNP, "elevation limit missing or invalid");
|
---|
212 | }
|
---|
213 |
|
---|
214 | return;
|
---|
215 | }
|
---|
216 |
|
---|
217 | LX200Generic::ISNewNumber (dev, name, values, names, n);
|
---|
218 | }
|
---|
219 |
|
---|
220 | void LX200Classic::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
|
---|
221 | {
|
---|
222 |
|
---|
223 | int index=0;
|
---|
224 |
|
---|
225 | // ignore if not ours //
|
---|
226 | if (strcmp (dev, thisDevice))
|
---|
227 | return;
|
---|
228 |
|
---|
229 | // Star Catalog
|
---|
230 | if (!strcmp (name, StarCatalogSP.name))
|
---|
231 | {
|
---|
232 | if (checkPower(&StarCatalogSP))
|
---|
233 | return;
|
---|
234 |
|
---|
235 | IUResetSwitch(&StarCatalogSP);
|
---|
236 | IUUpdateSwitch(&StarCatalogSP, states, names, n);
|
---|
237 | index = getOnSwitch(&StarCatalogSP);
|
---|
238 |
|
---|
239 | currentCatalog = LX200_STAR_C;
|
---|
240 |
|
---|
241 | if (selectSubCatalog(fd, currentCatalog, index))
|
---|
242 | {
|
---|
243 | currentSubCatalog = index;
|
---|
244 | StarCatalogSP.s = IPS_OK;
|
---|
245 | IDSetSwitch(&StarCatalogSP, NULL);
|
---|
246 | }
|
---|
247 | else
|
---|
248 | {
|
---|
249 | StarCatalogSP.s = IPS_IDLE;
|
---|
250 | IDSetSwitch(&StarCatalogSP, "Catalog unavailable");
|
---|
251 | }
|
---|
252 | return;
|
---|
253 | }
|
---|
254 |
|
---|
255 | // Deep sky catalog
|
---|
256 | if (!strcmp (name, DeepSkyCatalogSP.name))
|
---|
257 | {
|
---|
258 | if (checkPower(&DeepSkyCatalogSP))
|
---|
259 | return;
|
---|
260 |
|
---|
261 | IUResetSwitch(&DeepSkyCatalogSP);
|
---|
262 | IUUpdateSwitch(&DeepSkyCatalogSP, states, names, n);
|
---|
263 | index = getOnSwitch(&DeepSkyCatalogSP);
|
---|
264 |
|
---|
265 | if (index == LX200_MESSIER_C)
|
---|
266 | {
|
---|
267 | currentCatalog = index;
|
---|
268 | DeepSkyCatalogSP.s = IPS_OK;
|
---|
269 | IDSetSwitch(&DeepSkyCatalogSP, NULL);
|
---|
270 | return;
|
---|
271 | }
|
---|
272 | else
|
---|
273 | currentCatalog = LX200_DEEPSKY_C;
|
---|
274 |
|
---|
275 | if (selectSubCatalog(fd, currentCatalog, index))
|
---|
276 | {
|
---|
277 | currentSubCatalog = index;
|
---|
278 | DeepSkyCatalogSP.s = IPS_OK;
|
---|
279 | IDSetSwitch(&DeepSkyCatalogSP, NULL);
|
---|
280 | }
|
---|
281 | else
|
---|
282 | {
|
---|
283 | DeepSkyCatalogSP.s = IPS_IDLE;
|
---|
284 | IDSetSwitch(&DeepSkyCatalogSP, "Catalog unavailable");
|
---|
285 | }
|
---|
286 | return;
|
---|
287 | }
|
---|
288 |
|
---|
289 | // Solar system
|
---|
290 | if (!strcmp (name, SolarSP.name))
|
---|
291 | {
|
---|
292 |
|
---|
293 | if (checkPower(&SolarSP))
|
---|
294 | return;
|
---|
295 |
|
---|
296 | if (IUUpdateSwitch(&SolarSP, states, names, n) < 0)
|
---|
297 | return;
|
---|
298 |
|
---|
299 | index = getOnSwitch(&SolarSP);
|
---|
300 |
|
---|
301 | // We ignore the first option : "Select item"
|
---|
302 | if (index == 0)
|
---|
303 | {
|
---|
304 | SolarSP.s = IPS_IDLE;
|
---|
305 | IDSetSwitch(&SolarSP, NULL);
|
---|
306 | return;
|
---|
307 | }
|
---|
308 |
|
---|
309 | selectSubCatalog (fd, LX200_STAR_C, LX200_STAR);
|
---|
310 | selectCatalogObject(fd, LX200_STAR_C, index + 900);
|
---|
311 |
|
---|
312 | ObjectNoNP.s = IPS_OK;
|
---|
313 | SolarSP.s = IPS_OK;
|
---|
314 |
|
---|
315 | getObjectInfo(fd, ObjectInfoTP.tp[0].text);
|
---|
316 | IDSetNumber(&ObjectNoNP , "Object updated.");
|
---|
317 | IDSetSwitch(&SolarSP, NULL);
|
---|
318 |
|
---|
319 | if (currentCatalog == LX200_STAR_C || currentCatalog == LX200_DEEPSKY_C)
|
---|
320 | selectSubCatalog(fd, currentCatalog, currentSubCatalog);
|
---|
321 |
|
---|
322 | getObjectRA(fd, &targetRA);
|
---|
323 | getObjectDEC(fd, &targetDEC);
|
---|
324 |
|
---|
325 | handleCoordSet();
|
---|
326 |
|
---|
327 | return;
|
---|
328 | }
|
---|
329 |
|
---|
330 | LX200Generic::ISNewSwitch (dev, name, states, names, n);
|
---|
331 |
|
---|
332 | }
|
---|
333 |
|
---|
334 | void LX200Classic::ISPoll ()
|
---|
335 | {
|
---|
336 |
|
---|
337 | LX200Generic::ISPoll();
|
---|
338 |
|
---|
339 | }
|
---|
340 |
|
---|
341 | void LX200Classic::getBasicData()
|
---|
342 | {
|
---|
343 |
|
---|
344 | // process parent first
|
---|
345 | LX200Generic::getBasicData();
|
---|
346 |
|
---|
347 | }
|
---|