Instrument Neutral Distributed Interface INDI 2.2.5
arduino_st4.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2018 Jasem Mutlaq. All rights reserved.
3
4 Arduino ST4 Driver.
5
6 For this project: https://github.com/kevinferrare/arduino-st4
7
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2 of the License, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 The full GNU General Public License is included in this distribution in the
24 file called LICENSE.
25*******************************************************************************/
26
27#include "arduino_st4.h"
28
29#include "indicom.h"
31
32#include <cerrno>
33#include <cstring>
34#include <memory>
35#include <termios.h>
36#include <sys/ioctl.h>
37
38// We declare an auto pointer to ArduinoST4.
39std::unique_ptr<ArduinoST4> arduinoST4(new ArduinoST4());
40
41#define FLAT_TIMEOUT 3
42
44{
45 setVersion(1, 0);
46}
47
49{
51
53
55
57
58 serialConnection = new Connection::Serial(this);
59 serialConnection->registerHandshake([&]()
60 {
61 return Handshake();
62 });
64 // Arduino default port
65 serialConnection->setDefaultPort("/dev/ttyACM0");
66 registerConnection(serialConnection);
67
68 return true;
69}
70
78
80{
81 return static_cast<const char *>("Arduino ST4");
82}
83
84bool ArduinoST4::Handshake()
85{
86 if (isSimulation())
87 {
88 LOGF_INFO("Connected successfully to simulated %s.", getDeviceName());
89 return true;
90 }
91
92 PortFD = serialConnection->getPortFD();
93
94 return true;
95}
96
98{
99 sendCommand("DISCONNECT#");
100
102}
103
104bool ArduinoST4::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
105{
106 // Check guider interface
107 if (GI::processNumber(dev, name, values, names, n))
108 return true;
109
110 return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n);
111}
112
114{
115 LOGF_DEBUG("Guiding: N %.0f ms", ms);
116
117 if (GuideNSTID)
118 {
119 IERmTimer(GuideNSTID);
120 GuideNSTID = 0;
121 }
122
123 if (sendCommand("DEC+#") == false)
124 return IPS_ALERT;
125
126 guideDirection = ARD_N;
127 GuideNSTID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperN, this);
128 return IPS_BUSY;
129}
130
132{
133 LOGF_DEBUG("Guiding: S %.0f ms", ms);
134
135 if (GuideNSTID)
136 {
137 IERmTimer(GuideNSTID);
138 GuideNSTID = 0;
139 }
140
141 if (sendCommand("DEC-#") == false)
142 return IPS_ALERT;
143
144 guideDirection = ARD_S;
145 GuideNSTID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperS, this);
146 return IPS_BUSY;
147}
148
150{
151 LOGF_DEBUG("Guiding: E %.0f ms", ms);
152
153 if (GuideWETID)
154 {
155 IERmTimer(GuideWETID);
156 GuideWETID = 0;
157 }
158
159 if (sendCommand("RA+#") == false)
160 return IPS_ALERT;
161
162 guideDirection = ARD_E;
163 GuideWETID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperE, this);
164 return IPS_BUSY;
165}
166
168{
169 LOGF_DEBUG("Guiding: W %.0f ms", ms);
170
171 if (GuideWETID)
172 {
173 IERmTimer(GuideWETID);
174 GuideWETID = 0;
175 }
176
177 if (sendCommand("RA-#") == false)
178 return IPS_ALERT;
179
180 guideDirection = ARD_W;
181 GuideWETID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperE, this);
182 return IPS_BUSY;
183}
184
185//GUIDE The timer helper functions.
187{
188 static_cast<ArduinoST4 *>(p)->guideTimeout(ARD_N);
189}
191{
192 static_cast<ArduinoST4 *>(p)->guideTimeout(ARD_S);
193}
195{
196 static_cast<ArduinoST4 *>(p)->guideTimeout(ARD_W);
197}
199{
200 static_cast<ArduinoST4 *>(p)->guideTimeout(ARD_E);
201}
202
204{
205 if (direction == ARD_N || direction == ARD_S)
206 {
207 if (sendCommand("DEC0#"))
208 {
210 LOG_DEBUG("Guiding: DEC axis stopped.");
211 }
212 else
213 {
215 LOG_ERROR("Failed to stop DEC axis.");
216 }
217
218 GuideNSTID = 0;
219 GuideNSNP[0].setValue(0);
220 GuideNSNP[1].setValue(0);
222 }
223
224 if (direction == ARD_W || direction == ARD_E)
225 {
226 if (sendCommand("RA0#"))
227 {
229 LOG_DEBUG("Guiding: RA axis stopped.");
230 }
231 else
232 {
233 LOG_ERROR("Failed to stop RA axis.");
235 }
236
237 GuideWENP[0].setValue(0);
238 GuideWENP[1].setValue(0);
239 GuideWETID = 0;
241 }
242}
243
244bool ArduinoST4::sendCommand(const char *cmd)
245{
246 int nbytes_read = 0, nbytes_written = 0, tty_rc = 0;
247 char res[8] = {0};
248 LOGF_DEBUG("CMD <%s>", cmd);
249
250 if (!isSimulation())
251 {
252 tcflush(PortFD, TCIOFLUSH);
253 if ( (tty_rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
254 {
255 char errorMessage[MAXRBUF];
256 tty_error_msg(tty_rc, errorMessage, MAXRBUF);
257 LOGF_ERROR("Serial write error: %s", errorMessage);
258 return false;
259 }
260 }
261
262 if (isSimulation())
263 {
264 strncpy(res, "OK#", 8);
265 nbytes_read = 3;
266 }
267 else
268 {
269 if ( (tty_rc = tty_read_section(PortFD, res, '#', ARDUINO_TIMEOUT, &nbytes_read)) != TTY_OK)
270 {
271 char errorMessage[MAXRBUF];
272 tty_error_msg(tty_rc, errorMessage, MAXRBUF);
273 LOGF_ERROR("Serial read error: %s", errorMessage);
274 return false;
275 }
276 }
277
278 res[nbytes_read - 1] = '\0';
279 LOGF_DEBUG("RES <%s>", res);
280
281 return true;
282}
std::unique_ptr< ArduinoST4 > arduinoST4(new ArduinoST4())
virtual IPState GuideWest(uint32_t ms) override
Guide west for ms milliseconds. West is defined as RA-.
const char * getDefaultName() override
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
static void guideTimeoutHelperE(void *p)
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.
static void guideTimeoutHelperS(void *p)
virtual IPState GuideSouth(uint32_t ms) override
Guide south for ms milliseconds. South is defined as DEC-.
void guideTimeout(ARDUINO_DIRECTION direction)
virtual bool Disconnect() override
Disconnect from device.
static void guideTimeoutHelperW(void *p)
static void guideTimeoutHelperN(void *p)
virtual IPState GuideEast(uint32_t ms) override
Guide east for ms milliseconds. East is defined as RA+.
virtual IPState GuideNorth(uint32_t ms) override
Guide north for ms milliseconds. North is defined as DEC+.
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the initial connection to the devic...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
void setDefaultPort(const char *port)
setDefaultPort Set default port. Call this function in initProperties() of your driver if you want to...
const char * getDeviceName() const
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool Disconnect()
Disconnect from device.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
bool isSimulation() const
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
INDI::PropertyNumber GuideNSNP
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
INDI::PropertyNumber GuideWENP
void initProperties(const char *groupName)
Initialize guider properties. It is recommended to call this function within initProperties() of your...
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Call this function whenever client updates GuideNSNP or GuideWSP properties in the primary device....
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
const char * MOTION_TAB
MOTION_TAB Where all the motion control properties of the device are located.
void IERmTimer(int timerid)
Remove the timer with the given timerid, as returned from IEAddTimer() or IEAddPeriodicTimer().
Definition eventloop.c:606
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
Definition eventloop.c:586
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
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition indicom.c:653
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
Implementations for common driver routines.
@ TTY_OK
Definition indicom.h:54
#define MAXRBUF
Definition indidriver.c:52
#define LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOG_DEBUG(txt)
Definition indilogger.h:75
#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
uint8_t cmd[4]
Definition pwc-ioctl.h:2