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 | } |
---|