source: BAORadio/libindi/v1/drivers/filter_wheel/trutech_wheel.c @ 620

Last change on this file since 620 was 490, checked in by campagne, 14 years ago

import libindi (JEC)

File size: 10.4 KB
Line 
1#if 0
2   True Technology Filter Wheel
3    Copyright (C) 2006 Jasem Mutlaq (mutlaqja AT ikarustech DOT 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#endif
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <stdarg.h>
25#include <math.h>
26#include <unistd.h>
27#include <time.h>
28#include <fcntl.h>
29#include <errno.h>
30#include <sys/stat.h>
31#include <sys/time.h>
32#include <sys/types.h>
33#include <sys/socket.h>
34
35#include "indidevapi.h"
36#include "eventloop.h"
37#include "indicom.h"
38
39void ISInit(void);
40void getBasicData(void);
41void ISPoll(void *);
42void handleExposure(void *);
43void connectFilter(void);
44int  manageDefaults(char errmsg[]);
45int  checkPowerS(ISwitchVectorProperty *sp);
46int  checkPowerN(INumberVectorProperty *np);
47int  checkPowerT(ITextVectorProperty *tp);
48int  getOnSwitch(ISwitchVectorProperty *sp);
49int  isFilterConnected(void);
50
51static int targetFilter;
52static int fd;
53const unsigned char COMM_PRE  = 0x01;
54const unsigned char COMM_INIT = 0xA5;
55const unsigned char COMM_FILL = 0x20;
56
57#define mydev                           "TruTech Wheel"
58#define MAIN_GROUP                      "Main Control"
59#define currentFilter                   FilterPositionN[0].value
60#define POLLMS                          3000
61#define DEFAULT_FILTER_COUNT            5
62#define MAX_FILTER_COUNT                10
63#define ERRMSG_SIZE                     1024
64
65#define CMD_SIZE                        5
66#define CMD_JUNK                        64
67#define CMD_RESP                        15
68
69#define FILTER_TIMEOUT                  15                                      /* 15 Seconds before timeout */
70#define FIRST_FILTER                    1
71
72
73/*INDI controls */
74
75/* Connect/Disconnect */
76static ISwitch PowerS[]                 = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
77static ISwitchVectorProperty PowerSP    = { mydev, "CONNECTION" , "Connection", MAIN_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0};
78
79/* Connection Port */
80static IText PortT[]                    = {{"PORT", "Port", 0, 0, 0, 0}};
81static ITextVectorProperty PortTP               = { mydev, "DEVICE_PORT", "Ports", MAIN_GROUP, IP_RW, 0, IPS_IDLE, PortT, NARRAY(PortT), "", 0};
82
83/* Home/Learn Swtich */
84static ISwitch HomeS[]                  = {{"Find" , "" , ISS_OFF, 0, 0}};
85static ISwitchVectorProperty HomeSP     = { mydev, "HOME" , "", MAIN_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE, HomeS, NARRAY(HomeS), "", 0};
86
87/* Filter Count */
88static INumber FilterCountN[]     = { {"Count", "", "%2.0f",  0 , MAX_FILTER_COUNT, 1, DEFAULT_FILTER_COUNT, 0, 0, 0}};
89static INumberVectorProperty FilterCountNP = { mydev, "Filter Count", "", MAIN_GROUP, IP_RW, 0, IPS_IDLE, FilterCountN, NARRAY(FilterCountN), "", 0};
90
91/* Filter Position */
92static INumber FilterPositionN[]          = { {"FILTER_SLOT_VALUE", "Active Filter", "%2.0f",  1 , DEFAULT_FILTER_COUNT, 1, 1, 0, 0, 0}};
93static INumberVectorProperty FilterPositionNP = { mydev, "FILTER_SLOT", "Filter", MAIN_GROUP, IP_RW, 0, IPS_IDLE, FilterPositionN, NARRAY(FilterPositionN), "", 0};
94
95/* send client definitions of all properties */
96void ISInit()
97{
98        static int isInit=0;
99       
100        if (isInit)
101                return;
102       
103
104        targetFilter = -1;
105        fd = -1;
106
107        isInit = 1; 
108}
109
110void ISGetProperties (const char *dev)
111{ 
112
113        ISInit();
114       
115        if (dev && strcmp (mydev, dev))
116                return;
117       
118        /* Main Control */
119        IDDefSwitch(&PowerSP, NULL);
120        IDDefText(&PortTP, NULL);
121        IDDefNumber(&FilterCountNP, NULL);
122        IDDefSwitch(&HomeSP, NULL);
123        IDDefNumber(&FilterPositionNP, NULL);
124}
125
126void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) 
127{
128  INDI_UNUSED(dev);
129  INDI_UNUSED(name);
130  INDI_UNUSED(sizes);
131  INDI_UNUSED(blobsizes);
132  INDI_UNUSED(blobs);
133  INDI_UNUSED(formats);
134  INDI_UNUSED(names);
135  INDI_UNUSED(n);
136}
137void ISSnoopDevice (XMLEle *root) 
138{
139  INDI_UNUSED(root);
140}
141
142void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
143{
144        int err;
145        char error_message[ERRMSG_SIZE];
146
147        /* ignore if not ours */
148        if (dev && strcmp (dev, mydev))
149                return;
150           
151        ISInit();
152           
153        /* Connection */
154        if (!strcmp (name, PowerSP.name))
155        {
156                IUUpdateSwitch(&PowerSP, states, names, n);
157                connectFilter();
158                return;
159        }
160
161        /* Home Search */
162        if (!strcmp (name, HomeSP.name))
163        {
164                int nbytes=0;
165                unsigned char type = 0x03;
166                unsigned char chksum = COMM_INIT + type + COMM_FILL;
167                /*char filter_command[5] = { COMM_PRE, COMM_INIT, type, COMM_FILL, chksum };*/
168                char filter_command[CMD_SIZE];
169                snprintf(filter_command, CMD_SIZE,  "%c%c%c%c%c", COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
170
171                if (checkPowerS(&HomeSP))
172                        return;
173
174                err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
175               
176                /* Send Home Command */
177                if (err != TTY_OK)
178                {
179               
180                        tty_error_msg(err, error_message, ERRMSG_SIZE);
181                       
182                        HomeSP.s = IPS_ALERT;
183                        IDSetSwitch(&HomeSP, "Sending command Home to filter failed. %s", error_message);
184                        IDLog("Sending command Home to filter failed. %s\n", error_message);
185
186                        return;
187                }
188
189                FilterPositionN[0].value = 1;
190                FilterPositionNP.s = IPS_OK;
191                HomeSP.s = IPS_OK;
192                IDSetSwitch(&HomeSP, "Filter set to HOME.");
193                IDSetNumber(&FilterPositionNP, NULL);
194               
195        }
196       
197     
198}
199
200void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
201{
202        ISInit();
203       
204        /* ignore if not ours */ 
205        if (dev && strcmp (mydev, dev))
206                return;
207
208        if (!strcmp(name, PortTP.name))
209        {
210                if (IUUpdateText(&PortTP, texts, names, n))
211                  return;
212
213                PortTP.s = IPS_OK;
214                IDSetText(&PortTP, NULL);
215        }
216       
217}
218
219
220void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
221{
222        long err;
223        INumber *np;
224        n = n;
225       
226        /* ignore if not ours */
227        if (dev && strcmp (dev, mydev))
228            return;
229           
230        ISInit();
231       
232        if (!strcmp(FilterPositionNP.name, name)) 
233        {
234
235                if (!isFilterConnected()) 
236                {
237                        IDMessage(mydev, "Filter is not connected.");
238                        FilterPositionNP.s = IPS_IDLE;
239                        IDSetNumber(&FilterPositionNP, NULL);
240                        return;
241                }
242
243                np = IUFindNumber(&FilterPositionNP, names[0]);
244                if (np == &FilterPositionN[0])
245                {
246                       
247                        targetFilter = values[0];
248                        int nbytes=0;
249                        char type = 0x01;
250                        char chksum = COMM_INIT + type + (char) targetFilter;
251                        /*char filter_command[5] = { COMM_PRE, COMM_INIT, type, targetFilter, chksum };*/
252                        char filter_command[CMD_SIZE];
253
254                        snprintf(filter_command, CMD_SIZE,  "%c%c%c%c%c", COMM_PRE, COMM_INIT, type, COMM_FILL, chksum);
255
256                        if (targetFilter < FilterPositionN[0].min || targetFilter > FilterPositionN[0].max)
257                        {
258                                FilterPositionNP.s = IPS_ALERT;
259                                IDSetNumber(&FilterPositionNP, "Error: valid range of filter is from %d to %d", (int) FilterPositionN[0].min, (int) FilterPositionN[0].max);
260                                return;
261                        }
262
263                        IUUpdateNumber(&FilterPositionNP, values, names, n);
264                        err = tty_write(fd, filter_command, CMD_SIZE, &nbytes);
265
266                        FilterPositionNP.s = IPS_OK;
267                        IDSetNumber(&FilterPositionNP, "Setting current filter to slot %d", targetFilter);
268                }
269                else
270                {
271                        FilterPositionNP.s = IPS_IDLE;
272                        IDSetNumber(&FilterPositionNP, NULL);
273                }
274               
275                return;
276        }
277
278        if (!strcmp(FilterCountNP.name, name)) 
279        {
280
281                if (!isFilterConnected()) 
282                {
283                        IDMessage(mydev, "Filter is not connected.");
284                        FilterCountNP.s = IPS_IDLE;
285                        IDSetNumber(&FilterCountNP, NULL);
286                        return;
287                }
288
289                np = IUFindNumber(&FilterCountNP, names[0]);
290                if (np == &FilterCountN[0])
291                {
292                        if (IUUpdateNumber(&FilterCountNP, values, names, n) <0)
293                                return;
294
295                        FilterPositionN[0].min = 1;
296                        FilterPositionN[0].max = (int) FilterCountN[0].value;
297                        IUUpdateMinMax(&FilterPositionNP);
298
299                        FilterCountNP.s = IPS_OK;
300                        IDSetNumber(&FilterCountNP, "Updated number of available filters to %d", ((int) FilterCountN[0].value));
301                }
302                else
303                {
304                        FilterCountNP.s = IPS_IDLE;
305                        IDSetNumber(&FilterCountNP, NULL);
306                }
307               
308                return;
309        }
310
311}
312
313int getOnSwitch(ISwitchVectorProperty *sp)
314{
315  int i=0;
316 for (i=0; i < sp->nsp ; i++)
317 {
318     if (sp->sp[i].s == ISS_ON)
319      return i;
320 }
321
322 return -1;
323
324}
325
326int checkPowerS(ISwitchVectorProperty *sp)
327{
328
329  if (PowerSP.s != IPS_OK)
330  {
331    if (!strcmp(sp->label, ""))
332        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", sp->name);
333    else
334        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", sp->label);
335       
336    sp->s = IPS_IDLE;
337    IDSetSwitch(sp, NULL);
338    return -1;
339  }
340
341  return 0;
342}
343
344int checkPowerN(INumberVectorProperty *np)
345{
346  if (PowerSP.s != IPS_OK)
347  {
348     if (!strcmp(np->label, ""))
349        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", np->name);
350    else
351        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", np->label);
352   
353    np->s = IPS_IDLE;
354    IDSetNumber(np, NULL);
355    return -1;
356  }
357
358  return 0;
359}
360
361int checkPowerT(ITextVectorProperty *tp)
362{
363  if (PowerSP.s != IPS_OK)
364  {
365    if (!strcmp(tp->label, ""))
366        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", tp->name);
367    else
368        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", tp->label);
369       
370    tp->s = IPS_IDLE;
371    IDSetText(tp, NULL);
372    return -1;
373  }
374
375  return 0;
376
377}
378
379void connectFilter()
380{
381        int err;
382        char errmsg[ERRMSG_SIZE];
383 
384        switch (PowerS[0].s)
385        {
386                case ISS_ON:
387                        if ( (err = tty_connect(PortT[0].text, 9600, 8, 0, 1, &fd)) != TTY_OK)
388                        {
389                                PowerSP.s = IPS_ALERT;
390                                IDSetSwitch(&PowerSP, "Error: cannot connect to %s. Make sure the filter is connected and you have access to the port.", PortT[0].text);
391                                tty_error_msg(err, errmsg, ERRMSG_SIZE);
392                                IDLog("Error: %s\n", errmsg);
393                                return;
394                        }
395
396                        PowerSP.s = IPS_OK;
397                        IDSetSwitch(&PowerSP, "Filter Wheel is online. True Technology filter wheel suffers from several bugs. Please refer to http://indi.sf.net/profiles/trutech.html for more details.");
398                        break;
399               
400                case ISS_OFF:
401                        if ( (err = tty_disconnect(fd)) != TTY_OK)
402                        {
403                                PowerSP.s = IPS_ALERT;
404                                IDSetSwitch(&PowerSP, "Error: cannot disconnect.");
405                                tty_error_msg(err, errmsg, ERRMSG_SIZE);
406                                IDLog("Error: %s\n", errmsg);
407                                return;
408                        }
409
410                        PowerSP.s = IPS_IDLE;
411                        IDSetSwitch(&PowerSP, "Filter Wheel is offline.");
412                        break;
413        }
414}
415
416/* isFilterConnected: return 1 if we have a connection, 0 otherwise */
417int isFilterConnected(void)
418{
419   return ((PowerS[0].s == ISS_ON) ? 1 : 0);
420}
421
Note: See TracBrowser for help on using the repository browser.