1 /*
2 * scope_equinox.cpp
3 * PHD Guiding
4 *
5 * Created by Craig Stark.
6 * Copyright (c) 2008-2010 Craig Stark.
7 * All rights reserved.
8 *
9 * This source code is distributed under the following "BSD" license
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * Neither the name of Craig Stark, Stark Labs nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35 #include "phd.h"
36
37 #ifdef GUIDE_EQUINOX
38
39 #if defined (__APPLE__)
40 #include <CoreServices/CoreServices.h>
41 //#include <CoreServices/AppleEvents.h>
42 //#include <Foundation/Foundation.h>
43 //#include <AppleEvents.h>
44 //#include <AEDataModel.h>
45
46 // Code originally from Darryl @ Equinox
47
E6AESendRoutine(double ewCorrection,double nsCorrection,int mountcode)48 OSErr ScopeEquinox::E6AESendRoutine(double ewCorrection, double nsCorrection, int mountcode)
49 {
50 // correction values (+- seconds) to send to E6
51
52 OSErr err;
53 FourCharCode E6Sig = 'MPj6'; // the Equinox 6 creator signature
54 if (mountcode == SCOPE_EQMAC)
55 E6Sig = 'EQMC';
56 FourCharCode phdSig = 'PhDG'; // ***** you need to fill in your app signature here ******
57 AEAddressDesc addDesc;
58
59 AEEventClass evClass = 'phdG'; // the phd guide class.
60 AEEventID evID = 'evGD'; // the phd guide event.
61 AEKeyword keyObject;
62 AESendMode mode = kAEWaitReply; // you want something back
63
64 // create Apple Event with Equinox 6 signature
65
66 err = AECreateDesc( typeApplSignature, (Ptr) &E6Sig, sizeof(FourCharCode), &addDesc ); // make a description
67 if( err != noErr ) return err;
68
69 err = AECreateAppleEvent( evClass, evID, &addDesc, kAutoGenerateReturnID, kAnyTransactionID, &E6Event ); // create the AE
70 if( err != noErr ) {
71 AEDisposeDesc( &addDesc );
72 return err;
73 }
74
75 // create the return Apple Event with your signature (so I know where to send it)
76
77 err = AECreateDesc( typeApplSignature, (Ptr) &phdSig, sizeof(FourCharCode), &addDesc );
78 if( err != noErr ) {
79 AEDisposeDesc( &E6Event );
80 return err;
81 }
82
83 err = AECreateAppleEvent( evClass, evID, &addDesc, kAutoGenerateReturnID, kAnyTransactionID, &E6Return );
84 if( err != noErr ) {
85 AEDisposeDesc( &E6Event );
86 AEDisposeDesc( &addDesc );
87 return err;
88 }
89
90 // put the correction values into parameters - I have used doubles for a ew and ns seconds correction
91
92 keyObject = 'prEW'; // EW correction AE parameter (+ = east, - = west)
93 err = AEPutParamPtr( &E6Event, keyObject, typeIEEE64BitFloatingPoint, &ewCorrection, sizeof(double) );
94 if( err != noErr ) {
95 AEDisposeDesc( &E6Event );
96 AEDisposeDesc( &addDesc );
97 return err;
98 }
99
100 keyObject = 'prNS'; // NS correction AE parameter (+ = north, - = south)
101 err = AEPutParamPtr( &E6Event, keyObject, typeIEEE64BitFloatingPoint, &nsCorrection, sizeof(double) );
102 if( err != noErr ) {
103 AEDisposeDesc( &E6Event );
104 AEDisposeDesc( &addDesc );
105 return err;
106 }
107
108 // you now have the send AE, the return AE and the correction values in AE parameters - so send it!
109
110 err = AESendMessage( &E6Event, &E6Return, mode, kAEDefaultTimeout ); // you can specify a wait time (in ticks)
111 if( err != noErr ) { // Note: an error of -600 means E6 is not currently running
112 AEDisposeDesc( &E6Event );
113 AEDisposeDesc( &addDesc );
114 return err;
115 }
116
117 // at this point you have received the return AE from E6, so go read the return code (what do you want returned ??)
118 // the return code could indicate that E6 got the AE, can do it, or can't for some reason. You do NOT want to wait
119 // until the corrections have been applied - you should time that on your own.
120
121 keyObject = 'prRC'; // get return code
122 Size returnSize;
123 DescType returnType;
124 err = AEGetParamPtr( &E6Return, keyObject, typeSInt16, &returnType, &E6ReturnCode, sizeof(SInt16), &returnSize );
125
126 AEDisposeDesc( &E6Event );
127 AEDisposeDesc( &addDesc );
128 return 0;
129 }
130
Connect()131 bool ScopeEquinox::Connect()
132 {
133 // Check the E6 connection by sending 0,0 to it and checking E6Return
134 OSErr err = E6AESendRoutine(0.0,0.0,SCOPE_EQUINOX);
135 wxString prefix = "E6";
136 // if (mountcode == SCOPE_EQMAC) prefix = "EQMAC";
137 if (E6ReturnCode == -1) {
138 wxMessageBox (prefix + " responded it's not connected to a mount",_("Error"));
139 return true;
140 }
141 else if (err == -600) {
142 wxMessageBox (prefix + " not running",_("Error"));
143 return true;
144 }
145
146 Scope::Connect();
147
148 return false;
149 }
150
Guide(GUIDE_DIRECTION direction,int duration)151 Mount::MOVE_RESULT ScopeEquinox::Guide(GUIDE_DIRECTION direction, int duration)
152 {
153 double NSTime = 0.0;
154 double EWTime = 0.0;
155
156 switch (direction) {
157 case NORTH:
158 NSTime = (double) duration / 1000.0;
159 break;
160 case SOUTH:
161 NSTime = (double) duration / -1000.0;
162 break;
163 case EAST:
164 EWTime = (double) duration / 1000.0;
165 break;
166 case WEST:
167 EWTime = (double) duration / -1000.0;
168 break;
169 case NONE:
170 break;
171 }
172
173 OSErr err = E6AESendRoutine(EWTime, NSTime,SCOPE_EQUINOX);
174 wxString prefix = "E6";
175 //if (mountcode == SCOPE_EQMAC) prefix = "EQMAC";
176 if (E6ReturnCode == -1) {
177 pFrame->Alert(prefix + _(" responded it's not connected to a mount"));
178 return MOVE_ERROR;
179 }
180 else if (err == -600) {
181 pFrame->Alert(prefix + _(" not running"));
182 return MOVE_ERROR;
183 }
184 wxMilliSleep(duration);
185
186 return MOVE_OK;
187 }
188
189 #endif
190 #endif /* GUIDE_EQUINOX */
191