summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/indi/temmadriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/indi/temmadriver.c')
-rw-r--r--kstars/kstars/indi/temmadriver.c1000
1 files changed, 1000 insertions, 0 deletions
diff --git a/kstars/kstars/indi/temmadriver.c b/kstars/kstars/indi/temmadriver.c
new file mode 100644
index 00000000..55464493
--- /dev/null
+++ b/kstars/kstars/indi/temmadriver.c
@@ -0,0 +1,1000 @@
+#if 0
+ Temma INDI driver
+ Copyright (C) 2004 Francois Meyer (dulle @ free.fr)
+ Remi Petitdemange for the temma protocol
+ Reference site is http://dulle.free.fr/alidade/indi.php
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <time.h>
+
+#include "indicom.h"
+#include "indidevapi.h"
+#include "eventloop.h"
+#include "indicom.h"
+#include "temmadriver.h"
+
+
+ char errormes[][128]={
+ "I/O Timeout",
+ "Error reading from io port",
+ "Error writing to io port",
+ "Unrecognized message"
+ };
+
+char answer[32];
+int fd;
+int read_ret, write_ret;
+unsigned char buffer[256];
+unsigned char buffer2[256];
+
+
+#if 1
+/* Initlization routine */
+static void mountInit()
+{
+ static int inited; /* set once mountInit is called */
+
+ if (inited)
+ return;
+
+ /* setting default comm port */
+ PortT->text = realloc(PortT->text, 10);
+ TemmaNoteT[0].text = realloc( TemmaNoteT[0].text, 64);
+ TemmaNoteT[1].text = realloc( TemmaNoteT[1].text, 64);
+
+ if (!PortT->text || !TemmaNoteT[0].text || !TemmaNoteT[1].text){
+ fprintf(stderr,"Memory allocation error");
+ return;
+ }
+ strcpy(PortT->text, "/dev/ttyS0");
+ strcpy(TemmaNoteT[0].text, "Experimental Driver");
+ strcpy(TemmaNoteT[1].text, "http://dulle.free.fr/alidade/indi.php");
+
+ inited = 1;
+}
+#endif
+
+void ISGetProperties (const char *dev) {
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ mountInit();
+
+ IDDefSwitch (&powSw, NULL);
+ IDDefNumber (&eqTemma, NULL);
+ IDDefNumber (&eqNum, NULL);
+ IDDefSwitch (&OnCoordSetSw, NULL);
+ IDDefSwitch (&abortSlewSw, NULL);
+ IDDefText (&TemmaNoteTP, NULL);
+ IDDefSwitch (&RAmotorSw, NULL);
+ IDDefSwitch (&trackmodeSw, NULL);
+ IDDefText (&Port, NULL);
+ IDDefText (&TemmaVersion, NULL);
+ IDDefNumber (&Time, NULL);
+ IDDefNumber (&SDTime, NULL);
+ IDDefNumber (&cometNum, NULL);
+ IDDefNumber (&geoNum, NULL);
+}
+
+void ISNewBLOB (const char *dev, const char *name, int sizes[], char *blobs[], char *formats[], char *names[], int n)
+{
+ dev=dev;name=name;sizes=sizes;blobs=blobs;formats=formats;names=names;n=n;
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n) {
+ /*IText *tp;*/
+
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp (name, Port.name)) {
+ IUSaveText(PortT, texts[0]);
+ Port.s = IPS_OK;
+ IDSetText (&Port, NULL);
+ }
+ return;
+}
+
+/* client is sending us a new value for a Numeric vector property */
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n) {
+ /* ignore if not ours */
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp (name, eqNum.name)) {
+ /* new equatorial target coords */
+ /*double newra = 0, newdec = 0;*/
+ int i, nset;
+
+ /* Check power, if it is off, then return */
+ if (power[0].s != ISS_ON)
+ {
+ eqNum.s = IPS_IDLE;
+ IDSetNumber(&eqNum, "Power is off");
+ return;
+ }
+
+ for (nset = i = 0; i < n; i++) {
+ /* Find numbers with the passed names in the eqNum property */
+ INumber *eqp = IUFindNumber (&eqNum, names[i]);
+
+ /* If the number found is Right ascension (eq[0]) then process it */
+ if (eqp == &eq[0])
+ {
+ currentRA = (values[i]);
+ nset += currentRA >= 0 && currentRA <= 24;
+ }
+ /* Otherwise, if the number found is Declination (eq[1]) then process it */
+ else if (eqp == &eq[1]) {
+ currentDec = (values[i]);
+ nset += currentDec >= -90 && currentDec <= 90;
+ }
+ } /* end for */
+
+ /* Did we process the two numbers? */
+ if (nset == 2) {
+ /*char r[32], d[32];*/
+
+ /* Set the mount state to BUSY */
+ eqNum.s = IPS_BUSY;
+
+ if (SLEWSW==ISS_ON || TRACKSW==ISS_ON){
+ IDSetNumber(&eqNum, "Moving to RA Dec %f %f", currentRA,
+ currentDec);
+ do_TemmaGOTO();
+ }
+
+ if (SYNCSW==ISS_ON){
+ IDSetNumber(&eqNum, "Syncing to RA Dec %f %f", currentRA, currentDec);
+ set_TemmaCurrentpos();
+ }
+ eqNum.s = IPS_OK;
+ IDSetNumber(&eqNum, "Synced");
+ }
+ /* We didn't process the two number correctly, report an error */
+ else {
+ /* Set property state to idle */
+ eqNum.s = IPS_IDLE;
+
+ IDSetNumber(&eqNum, "RA or Dec absent or bogus.");
+ }
+ return;
+ }
+}
+
+/* client is sending us a new value for a Switch property */
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ ISwitch *sp;
+
+ /* ignore if not ours */
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp (name, powSw.name)) {
+ sp = IUFindSwitch (&powSw, names[0]);
+ if (!sp)
+ return;
+
+ fprintf(stderr,"new state %s\n",names[0]);
+
+ sp->s = states[0];
+ if (!strcmp(names[0],"CONNECT")) {
+ connectMount();
+ }
+ if (!strcmp(names[0],"DISCONNECT")) {
+ disconnectMount();
+ }
+ }
+
+ if (!strcmp (name, abortSlewSw.name)) {
+ if (POWSW){
+ TemmaabortSlew();
+ IDSetSwitch (&abortSlewSw, "Abort slew");
+ }
+ else {
+ IDSetSwitch (&abortSlewSw, "Power is off");
+ }
+ }
+
+ if (!strcmp (name, RAmotorSw.name)) {
+ if (POWSW){
+ sp = IUFindSwitch (&RAmotorSw, names[0]);
+ if (!sp)
+ return;
+
+ fprintf(stderr,"new state %s\n",names[0]);
+
+ sp->s = states[0];
+
+ RAmotorSw.s = IPS_BUSY;
+ if (!strcmp(names[0],"RUN")) {
+ set_TemmaStandbyState(0);
+ }
+
+ if (!strcmp(names[0],"STOP")) {
+ set_TemmaStandbyState(1);
+ }
+
+ if(get_TemmaStandbyState(buffer)){
+ RAmotorSw.s = IPS_IDLE;
+ IDSetSwitch (&RAmotorSw, "Error writing to port");
+ return;
+ }
+ }
+ else {
+ IDSetSwitch (&RAmotorSw, "Power is off");
+ }
+ }
+
+ if (!strcmp (name, OnCoordSetSw.name)) {
+ if (POWSW){
+ IUResetSwitches(&OnCoordSetSw);
+ sp = IUFindSwitch (&OnCoordSetSw, names[0]);
+ if (!sp)
+ return;
+
+ fprintf(stderr,"new state %s\n",names[0]);
+
+ sp->s = states[0];
+
+ IUResetSwitches(&OnCoordSetSw);
+ IUUpdateSwitches(&OnCoordSetSw, states, names, n);
+ /* currentSet = getOnSwitch(&OnCoordSetSw); */
+ OnCoordSetSw.s = IPS_OK;
+ IDSetSwitch(&OnCoordSetSw, NULL);
+ }
+ else {
+ IDSetSwitch (&OnCoordSetSw, "Power is off");
+ }
+ }
+}
+
+double calcLST(char *strlst){
+ time_t computertime;
+ struct tm gmt;
+ double jd, gmst;
+ double lst;
+ /*int a,b;*/
+
+ time(&computertime);
+ gmtime_r(&computertime, &gmt);
+ gmt.tm_mon+=1;
+ gmt.tm_year+=1900;
+ currentUTC=(double)gmt.tm_hour+(double)gmt.tm_min/60+(double)gmt.tm_sec/3600;
+
+ jd=UTtoJD(&gmt);
+ gmst=JDtoGMST(jd);
+
+ lst=(gmst-longitude)/15;
+
+ lst=(lst/24-(int)(lst/24))*24;
+
+ if(lst>=24)
+ lst-=24;
+ sprintf(strlst,"%.2d%.2d%.2d", (int)lst,
+ ((int)(lst*60))%60,
+ ((int)(lst*3600))%60);
+ currentLST=lst;
+ IDSetNumber (&SDTime, NULL);
+ IDSetNumber (&Time, NULL);
+
+ return 0;
+}
+
+#if 1
+/* update the mount over time */
+void readMountcurrentpos (void *p)
+{
+ char result[32];
+
+ if(POWSW){
+ get_TemmaCurrentpos(result);
+ calcLST(result);
+
+ /* This is a temporary workaround to allow
+ clients with only one eq property to work */
+ currentRA=temmaRA;
+ currentDec=temmaDec;
+
+ /* again */
+ IEAddTimer (POLLMS, readMountcurrentpos, NULL);
+ }
+}
+#endif
+
+static void connectMount () {
+ fprintf(stderr,"opening mount port %s\n",PortT->text);
+ if (power[0].s == ISS_ON){
+ if (Port.s != IPS_OK){
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+
+ IDSetSwitch (&powSw, "Port not set.");
+ return;
+ }
+ else {
+ if (TemmaConnect(PortT->text)==0){
+ IDSetText (&Port, "Port is opened.");
+ if( !get_TemmaVERSION(buffer)){
+ powSw.s = IPS_OK;
+ power[0].s = ISS_ON;
+ power[1].s = ISS_OFF;
+ snprintf(buffer2,sizeof( buffer2 ),"%s",buffer+4);
+
+ IDSetText(&TemmaVersion , "Temma version set");
+ TemmaVersionT->text = realloc(TemmaVersionT->text, strlen(buffer2)+1);
+ if (!TemmaVersionT->text){
+ fprintf(stderr,"Memory allocation error");
+ return;
+ }
+ IDSetSwitch (&powSw, "Mount is ready");
+ IDSetSwitch (&powSw, VERSION);
+
+ strcpy(TemmaVersionT->text, buffer2);
+ TemmaVersion.s = IPS_OK;
+ IDSetText (&TemmaVersion, NULL);
+ IDLog("%s", buffer2);
+ /* start timer to read mount coords */
+ IEAddTimer (POLLMS, readMountcurrentpos, NULL);
+ }
+ else {
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+ power[1].s = ISS_ON;
+ IDSetText(&Port , "Com error");
+ IDSetSwitch (&powSw, "Port not set.");
+ }
+
+ if(get_TemmaStandbyState(answer)){
+ IDSetSwitch (&RAmotorSw, "Error writing to port");
+ return;
+ }
+ }
+ else {
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+ power[1].s = ISS_ON;
+
+ IDSetSwitch (&powSw, "Failed to open port.");
+ }
+ }
+ }
+}
+
+static void disconnectMount () {
+ fprintf(stderr,"closing mount port %s\n",PortT->text);
+ if (power[1].s == ISS_ON){
+ if (Port.s != IPS_OK){
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+
+ IDSetSwitch (&powSw, "Port not set.");
+ return;
+ }
+ else {
+ TemmaDisconnect();
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+
+ IDSetSwitch (&powSw, "Port is closed.");
+ }
+ }
+ else {
+ fprintf(stderr, "Already disconnected \n");
+ }
+}
+
+int TemmaConnect(const char *device) {
+ fprintf(stderr, "Connecting to device %s\n", device);
+
+ if (openPort(device) < 0){
+ fprintf(stderr, "Error connecting to device %s\n", device);
+ return -1;
+ }
+ else{
+ return 0;
+ }
+}
+
+int TemmaDisconnect() {
+ fprintf(stderr, "Disconnected.\n");
+ close(fd);
+
+ return 0;
+}
+
+int set_CometTracking(int RArate, int DECrate){
+#if 0
+ Set Comet Tracking
+ LM+/-99999,+/-9999
+ RA : Adjust Sidereal time by seconds per Day
+
+ DEC : Adjust DEC tracking by Minutes Per Day
+ valeur DEC min=-600 /max=+600 (+/-10 deg / jour)
+
+ Example:
+ LM+120,+30 would slow the RA speed by 86164/86284 and
+ the Dec would track at 30 Minutes a day.
+ To stop tracking either send a LM0,0 (or a PS
+ sauf erreur on constate en faite l inverse en RA
+ retour Vsideral => LM0,0 ou LM+0,+0
+#endif
+ char local_buffer[16];
+
+ if (RArate<-21541){
+ RArate=-21541;
+ }
+
+ if (RArate>21541){
+ RArate=21541;
+ }
+
+ if (DECrate<-600){
+ DECrate=-600;
+ }
+
+ if (DECrate>600){
+ DECrate=600;
+ }
+
+ snprintf(local_buffer, sizeof( local_buffer ), "%+6d,%+5d", RArate, DECrate);
+ set_TemmaCometTracking(local_buffer);
+
+ return 0;
+}
+
+int TemmaabortSlew() {
+ if (portWrite("PS") < 0)
+ return -1;
+
+ return 0;
+}
+
+int do_TemmaGOTO() {
+ /* Temma Sync */
+ char command[16];
+ char sign;
+ double dec;
+
+ calcLST(buffer);
+ set_TemmaLST(buffer);
+
+ dec=fabs(currentDec);
+ if (currentDec>0){
+ sign='+';
+ }
+ else {
+ sign='-';
+ }
+
+ snprintf(buffer, sizeof(buffer),"%.2d%.2d%.2d%c%.2d%.2d%.1d",
+ (int)currentRA,(int)(currentRA*(double)60)%60,((int)(currentRA*(double)6000))%100,sign,
+ (int)dec,(int)(dec*(double)60)%60,((int)(dec*(double)600))%10);
+ fprintf(stderr,"Goto %s\n", buffer);
+
+ snprintf(command,14,"P%s",buffer);
+ buffer[14]=0;
+ fprintf(stderr,"Goto command:%s\n", command);
+ portWrite(command);
+
+ portRead(buffer,-1,TEMMA_TIMEOUT);
+ if(command[0]=='R'){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int extractRA(char *buf){
+ int r,h,m,s;
+ /*double dra;*/
+
+ r=atoi(buf);
+ h=r/10000;
+ m=r/100-100*h;
+ s=(r%100)*.6;
+ temmaRA=((double)h+((double)m + (double)s/60)/60);
+ IDSetNumber (&eqTemma, NULL);
+ /* fprintf(stderr,"extractRA: %s %d %d %d %d %lf\n",buf,r,h,m,s,dra);*/
+ return 0;
+}
+
+int extractDEC(char *buf){
+ int dec,d,m,s;
+ /*double ddec;*/
+
+ dec=atoi(buf+1);
+ d=dec/1000;
+ m=dec/10-100*d;
+ s=(dec%10)*6;
+ temmaDec=((double)d+((double)m + (double)s/60)/60);
+ if (*buf=='-')
+ temmaDec*=-1;
+
+ IDSetNumber (&eqTemma, NULL);
+
+
+ /* fprintf(stderr,"extractDEC: %s %d %d %d %d %lf\n",buf,dec,d,m,s,ddec);*/
+ return 0;
+}
+
+
+int get_TemmaCurrentpos(char *local_buffer){
+ char buf[16];
+
+ if (portWrite("E") < 0)
+ return -1;
+
+ if(portRead(local_buffer,-1,TEMMA_TIMEOUT)==SUCCESS){
+ if(strstr(local_buffer, "E")==local_buffer){
+ strncpy(buf,local_buffer+1,6);
+ buf[6]=0;
+ extractRA(buf);
+
+ strncpy(buf,local_buffer+7,6);
+ buf[6]=0;
+ extractDEC(buf);
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int set_TemmaCurrentpos(void) {
+ /* Temma Sync */
+ char buf[16], sign;
+ double dec;
+
+ calcLST(buf);
+ set_TemmaLST(buf);
+ portWrite("Z");
+ calcLST(buf);
+ set_TemmaLST(buf);
+
+ dec=fabs(currentDec);
+ if (currentDec>0){
+ sign='+';
+ }
+ else {
+ sign='-';
+ }
+
+ sprintf(buffer,"%.2d%.2d%.2d%c%.2d%.2d%.1d",
+ (int)currentRA,(int)(currentRA*(double)60)%60,((int)(currentRA*(double)6000))%100,sign,
+ (int)dec,(int)(dec*(double)60)%60,((int)(dec*(double)600))%10);
+ fprintf(stderr,"sync to %s %f %f\n", buffer,currentRA,dec);
+
+ snprintf(buf, sizeof(buf), "D%s",buffer);
+ buf[13]=0;
+ portWrite(buf);
+ *buffer=0;
+
+ portRead(buffer,-1,TEMMA_TIMEOUT);
+ if(buffer[0]=='R'){
+ return 0;
+ }
+ else{
+ return -1;
+ }
+}
+
+int do_TemmaSLEW(char mode){
+ /*char command[16];*/
+
+ sprintf(buffer,"M%c",mode); /* see bit definition in Temmadriver.h */
+
+ if (portWrite(buffer) < 0)
+ return -1;
+
+ return 0;
+}
+
+int get_TemmaVERSION(char *local_buffer){
+ int err;
+
+ if ((err=portWrite("v")) < 0){
+ return err;
+ }
+
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "ver")==local_buffer){
+ return 0;
+ }
+ else
+ return EREAD;
+}
+
+int get_TemmaGOTOstatus(char *local_buffer){
+ /*
+ 0 no ongoing goto
+ 1 ongoing Goto
+ -1 error
+ */
+ if (portWrite("s") < 0)
+ return -1;
+
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "s")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int get_TemmaBOTHcorrspeed(char *local_buffer){
+ if (portWrite("lg") < 0)
+ return -1;
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "lg")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int get_TemmaDECcorrspeed(char *local_buffer){
+ if (portWrite("lb") < 0)
+ return -1;
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "lb")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int set_TemmaDECcorrspeed(char *local_buffer){
+ char command[16];
+
+ snprintf(command, 4, "LB%s",local_buffer);
+
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+int get_TemmaRAcorrspeed(char *local_buffer){
+ if (portWrite("la") < 0)
+ return -1;
+
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "la")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int set_TemmaRAcorrspeed(char *local_buffer){
+ char command[16];
+
+ snprintf(command, 4,"LA%s",local_buffer);
+
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+int get_TemmaLatitude(char *local_buffer){
+ if (portWrite("i") < 0)
+ return -1;
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(local_buffer[0]=='i'){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int set_TemmaLatitude(char *local_buffer){
+ char command[16];
+ double lat;
+ char sign;
+
+ lat=fabs(latitude);
+ if (latitude>0){
+ sign='+';
+ }
+ else {
+ sign='-';
+ }
+
+ sprintf(command,"I%c%.2d%.2d%.1d", sign,
+ (int)lat,
+ (int)(lat*(double)60)%60,
+ ((int)(lat*(double)600))%10);
+
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+int get_TemmaLST(char *local_buffer){
+ if (portWrite("g") < 0)
+ return -1;
+
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(local_buffer[0]=='g'){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+int set_TemmaLST(char *local_buffer){
+ char command[16];
+ snprintf(command,7,"T%s",local_buffer);
+
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+
+int get_TemmaCometTracking(char *local_buffer){
+ if (portWrite("lm") < 0)
+ return -1;
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "lm")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int set_TemmaStandbyState(int on){
+ if (on){
+ return portWrite("STN-ON");
+ }
+ else{
+ return portWrite("STN-OFF");
+ }
+ return 0;
+}
+
+int get_TemmaStandbyState(unsigned char *local_buffer){
+ int nb;
+ int status;
+
+ if ((nb=portWrite("STN-COD")) < 0){
+ IDSetSwitch (&RAmotorSw, "I/O error when asking RAmotor status");
+ return -1;
+ }
+
+ if((status=portRead(local_buffer,-1,TEMMA_TIMEOUT)==SUCCESS)){
+ if(strstr(local_buffer, "stn")==local_buffer){
+ local_buffer[7]=0;
+ if (strstr(local_buffer,"on")){ /* stanby on */
+ RAmotorSw.s = IPS_OK;
+ RAmotor[0].s = ISS_OFF;
+ RAmotor[1].s = ISS_ON;
+ IDSetSwitch (&RAmotorSw, "RA motor is off.");
+ }
+ else{
+ if (strstr(local_buffer,"off")){ /* stanby off */
+ RAmotorSw.s = IPS_OK;
+ RAmotor[0].s = ISS_ON;
+ RAmotor[1].s = ISS_OFF;
+ IDSetSwitch (&RAmotorSw, "RA motor is on.");
+ }
+ else {
+ RAmotorSw.s = IPS_OK;
+ IDSetSwitch (&RAmotorSw, "I/O error when getting RAmotor status");
+ }
+ }
+ }
+ return 0;
+ }
+ if (status<=ETIMEOUT && status >=ECOMMAND){
+ IDSetSwitch(&RAmotorSw, "%s", errormes[ETIMEOUT - status]);
+ }
+
+ return -1;
+}
+
+int set_TemmaCometTracking(char *local_buffer){
+ char command[16];
+
+ snprintf(command,15,"LM%s",local_buffer);
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+int set_TemmaSolarRate(void){
+ if (portWrite("LK") < 0)
+ return -1;
+ return 0;
+}
+
+int set_TemmaStellarRate(void){
+ if (portWrite("LL") < 0)
+ return -1;
+ return 0;
+}
+
+
+int switch_Temmamountside(void){
+ if (portWrite("PT") < 0)
+ return -1;
+ return 0;
+}
+
+/**********************************************************************
+ * Comm
+ **********************************************************************/
+
+int openPort(const char *portID) {
+ struct termios ttyOptions;
+
+ if ( (fd = open(portID, O_RDWR)) == -1)
+ return -1;
+ memset(&ttyOptions, 0, sizeof(ttyOptions));
+ tcgetattr(fd, &ttyOptions);
+
+ /* 8 bit, enable read */
+ ttyOptions.c_cflag |= CS8;
+ /* parity */
+ ttyOptions.c_cflag |= PARENB;
+ ttyOptions.c_cflag &= ~PARODD;
+ ttyOptions.c_cflag &= ~CSTOPB;
+ ttyOptions.c_cflag |= CRTSCTS;
+
+ /* set baud rate */
+ cfsetispeed(&ttyOptions, B19200);
+ cfsetospeed(&ttyOptions, B19200);
+
+ /* set input/output flags */
+ ttyOptions.c_iflag = IGNBRK;
+
+ /* Read at least one byte */
+ ttyOptions.c_cc[VMIN] = 1;
+ ttyOptions.c_cc[VTIME] = 5;
+
+ /* Misc. */
+ ttyOptions.c_lflag = 0;
+ ttyOptions.c_oflag = 0;
+
+ /* set attributes */
+ tcsetattr(fd, TCSANOW, &ttyOptions);
+
+ /* flush the channel */
+ tcflush(fd, TCIOFLUSH);
+ return (fd);
+}
+
+int portWrite(char * buf) {
+ int nbytes=strlen(buf); /*, totalBytesWritten;*/
+ int bytesWritten = 0;
+ /*int retry=10;*/
+
+ bytesWritten = write(fd, buf, nbytes);
+ bytesWritten += write(fd, "\r\n", 2);
+ /*fprintf(stderr,"portwrite :%d octets %s\n", bytesWritten, buf);*/
+
+ if (bytesWritten!=nbytes+2){
+ perror("write error: ");
+ IDLog("Error writing to port");
+ return EWRITE;
+ }
+ return (bytesWritten);
+}
+
+int portRead(char *buf, int nbytes, int timeout) {
+ /*
+ A very basic finite state machine monitors
+ the bytes read ;
+ state 0 : read regular bytes
+ state 1 : just read a \n, waiting for a \r
+ state 2 : read a \n and a \r, command is over.
+
+ Not sure it is useful here but I use a more
+ sophisticated version of this with a GPS receiver
+ and it is robust and reliable
+
+ We return a null terminated string.
+ */
+
+ int bytesRead = 0, state=0, /*i=0,*/ current=0;
+ /*int totalBytesRead = 0;*/
+ int err;
+
+ if ( (err = TemmareadOut(timeout)) ){
+ switch (err){
+ case ETIMEOUT:
+ IDLog("Error: timeout while reading");
+ return err;
+ }
+ }
+
+ while (read(fd,buf+bytesRead,1)==1){
+ /* fprintf(stderr,"%c",buf[bytesRead]); */
+ fflush(NULL);
+ switch (state) {
+ case 0:
+ if(buf[bytesRead]==13)
+ state=1;
+ break;
+
+ case 1:
+ if(buf[bytesRead]==10)
+ state=2;
+ else
+ if(buf[bytesRead]==13)
+ state=1;
+ else
+ state=0;
+ break;
+ }
+
+ ++current;
+
+ if (state==2){
+ /*process(buf);*/
+ buf[bytesRead+1]=0;
+ state=current=0;
+ return SUCCESS;
+ }
+
+ bytesRead=current;
+ }
+ return state;
+}
+
+int TemmareadOut(int timeout) {
+ struct timeval tv;
+ fd_set readout;
+ int retval;
+
+ FD_ZERO(&readout);
+ FD_SET(fd, &readout);
+
+ /* wait for 'timeout' seconds */
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ /* Wait till we have a change in the fd status */
+ retval = select (fd+1, &readout, NULL, NULL, &tv);
+
+ /* Return 0 on successful fd change */
+ if (retval > 0)
+ return 0;
+ /* Return -1 due to an error */
+ else if (retval == EREAD)
+ return retval;
+ /* Return -2 if time expires before anything interesting happens */
+ else {
+ return ETIMEOUT;
+ }
+}
+