moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / indi / temmadriver.c
blob968cd1b8cf8b356e60e0b83ecaa952908f2ecaee
1 #if 0
2 Temma INDI driver
3 Copyright (C) 2004 Francois Meyer (dulle @ free.fr)
4 Remi Petitdemange for the temma protocol
5 Reference site is http://dulle.free.fr/alidade/indi.php
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <math.h>
28 #include <sys/time.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <termios.h>
32 #include <time.h>
34 #include "indicom.h"
35 #include "indidevapi.h"
36 #include "eventloop.h"
37 #include "indicom.h"
38 #include "temmadriver.h"
41 char errormes[][128]={
42 "I/O Timeout",
43 "Error reading from io port",
44 "Error writing to io port",
45 "Unrecognized message"
48 char answer[32];
49 int fd;
50 int read_ret, write_ret;
51 unsigned char buffer[256];
52 unsigned char buffer2[256];
55 #if 1
56 /* Initlization routine */
57 static void mountInit()
59 static int inited; /* set once mountInit is called */
61 if (inited)
62 return;
64 /* setting default comm port */
65 PortT->text = realloc(PortT->text, 10);
66 TemmaNoteT[0].text = realloc( TemmaNoteT[0].text, 64);
67 TemmaNoteT[1].text = realloc( TemmaNoteT[1].text, 64);
69 if (!PortT->text || !TemmaNoteT[0].text || !TemmaNoteT[1].text){
70 fprintf(stderr,"Memory allocation error");
71 return;
73 strcpy(PortT->text, "/dev/ttyS0");
74 strcpy(TemmaNoteT[0].text, "Experimental Driver");
75 strcpy(TemmaNoteT[1].text, "http://dulle.free.fr/alidade/indi.php");
77 inited = 1;
79 #endif
81 void ISGetProperties (const char *dev) {
82 if (dev && strcmp (mydev, dev))
83 return;
85 mountInit();
87 IDDefSwitch (&powSw, NULL);
88 IDDefNumber (&eqTemma, NULL);
89 IDDefNumber (&eqNum, NULL);
90 IDDefSwitch (&OnCoordSetSw, NULL);
91 IDDefSwitch (&abortSlewSw, NULL);
92 IDDefText (&TemmaNoteTP, NULL);
93 IDDefSwitch (&RAmotorSw, NULL);
94 IDDefSwitch (&trackmodeSw, NULL);
95 IDDefText (&Port, NULL);
96 IDDefText (&TemmaVersion, NULL);
97 IDDefNumber (&Time, NULL);
98 IDDefNumber (&SDTime, NULL);
99 IDDefNumber (&cometNum, NULL);
100 IDDefNumber (&geoNum, NULL);
103 void ISNewBLOB (const char *dev, const char *name, int sizes[], char *blobs[], char *formats[], char *names[], int n)
105 dev=dev;name=name;sizes=sizes;blobs=blobs;formats=formats;names=names;n=n;
108 void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n) {
109 /*IText *tp;*/
111 if (strcmp (dev, mydev))
112 return;
114 if (!strcmp (name, Port.name)) {
115 IUSaveText(PortT, texts[0]);
116 Port.s = IPS_OK;
117 IDSetText (&Port, NULL);
119 return;
122 /* client is sending us a new value for a Numeric vector property */
123 void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n) {
124 /* ignore if not ours */
125 if (strcmp (dev, mydev))
126 return;
128 if (!strcmp (name, eqNum.name)) {
129 /* new equatorial target coords */
130 /*double newra = 0, newdec = 0;*/
131 int i, nset;
133 /* Check power, if it is off, then return */
134 if (power[0].s != ISS_ON)
136 eqNum.s = IPS_IDLE;
137 IDSetNumber(&eqNum, "Power is off");
138 return;
141 for (nset = i = 0; i < n; i++) {
142 /* Find numbers with the passed names in the eqNum property */
143 INumber *eqp = IUFindNumber (&eqNum, names[i]);
145 /* If the number found is Right ascension (eq[0]) then process it */
146 if (eqp == &eq[0])
148 currentRA = (values[i]);
149 nset += currentRA >= 0 && currentRA <= 24;
151 /* Otherwise, if the number found is Declination (eq[1]) then process it */
152 else if (eqp == &eq[1]) {
153 currentDec = (values[i]);
154 nset += currentDec >= -90 && currentDec <= 90;
156 } /* end for */
158 /* Did we process the two numbers? */
159 if (nset == 2) {
160 /*char r[32], d[32];*/
162 /* Set the mount state to BUSY */
163 eqNum.s = IPS_BUSY;
165 if (SLEWSW==ISS_ON || TRACKSW==ISS_ON){
166 IDSetNumber(&eqNum, "Moving to RA Dec %f %f", currentRA,
167 currentDec);
168 do_TemmaGOTO();
171 if (SYNCSW==ISS_ON){
172 IDSetNumber(&eqNum, "Syncing to RA Dec %f %f", currentRA, currentDec);
173 set_TemmaCurrentpos();
175 eqNum.s = IPS_OK;
176 IDSetNumber(&eqNum, "Synced");
178 /* We didn't process the two number correctly, report an error */
179 else {
180 /* Set property state to idle */
181 eqNum.s = IPS_IDLE;
183 IDSetNumber(&eqNum, "RA or Dec absent or bogus.");
185 return;
189 /* client is sending us a new value for a Switch property */
190 void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
192 ISwitch *sp;
194 /* ignore if not ours */
195 if (strcmp (dev, mydev))
196 return;
198 if (!strcmp (name, powSw.name)) {
199 sp = IUFindSwitch (&powSw, names[0]);
200 if (!sp)
201 return;
203 fprintf(stderr,"new state %s\n",names[0]);
205 sp->s = states[0];
206 if (!strcmp(names[0],"CONNECT")) {
207 connectMount();
209 if (!strcmp(names[0],"DISCONNECT")) {
210 disconnectMount();
214 if (!strcmp (name, abortSlewSw.name)) {
215 if (POWSW){
216 TemmaabortSlew();
217 IDSetSwitch (&abortSlewSw, "Abort slew");
219 else {
220 IDSetSwitch (&abortSlewSw, "Power is off");
224 if (!strcmp (name, RAmotorSw.name)) {
225 if (POWSW){
226 sp = IUFindSwitch (&RAmotorSw, names[0]);
227 if (!sp)
228 return;
230 fprintf(stderr,"new state %s\n",names[0]);
232 sp->s = states[0];
234 RAmotorSw.s = IPS_BUSY;
235 if (!strcmp(names[0],"RUN")) {
236 set_TemmaStandbyState(0);
239 if (!strcmp(names[0],"STOP")) {
240 set_TemmaStandbyState(1);
243 if(get_TemmaStandbyState(buffer)){
244 RAmotorSw.s = IPS_IDLE;
245 IDSetSwitch (&RAmotorSw, "Error writing to port");
246 return;
249 else {
250 IDSetSwitch (&RAmotorSw, "Power is off");
254 if (!strcmp (name, OnCoordSetSw.name)) {
255 if (POWSW){
256 IUResetSwitches(&OnCoordSetSw);
257 sp = IUFindSwitch (&OnCoordSetSw, names[0]);
258 if (!sp)
259 return;
261 fprintf(stderr,"new state %s\n",names[0]);
263 sp->s = states[0];
265 IUResetSwitches(&OnCoordSetSw);
266 IUUpdateSwitches(&OnCoordSetSw, states, names, n);
267 /* currentSet = getOnSwitch(&OnCoordSetSw); */
268 OnCoordSetSw.s = IPS_OK;
269 IDSetSwitch(&OnCoordSetSw, NULL);
271 else {
272 IDSetSwitch (&OnCoordSetSw, "Power is off");
277 double calcLST(char *strlst){
278 time_t computertime;
279 struct tm gmt;
280 double jd, gmst;
281 double lst;
282 /*int a,b;*/
284 time(&computertime);
285 gmtime_r(&computertime, &gmt);
286 gmt.tm_mon+=1;
287 gmt.tm_year+=1900;
288 currentUTC=(double)gmt.tm_hour+(double)gmt.tm_min/60+(double)gmt.tm_sec/3600;
290 jd=UTtoJD(&gmt);
291 gmst=JDtoGMST(jd);
293 lst=(gmst-longitude)/15;
295 lst=(lst/24-(int)(lst/24))*24;
297 if(lst>=24)
298 lst-=24;
299 sprintf(strlst,"%.2d%.2d%.2d", (int)lst,
300 ((int)(lst*60))%60,
301 ((int)(lst*3600))%60);
302 currentLST=lst;
303 IDSetNumber (&SDTime, NULL);
304 IDSetNumber (&Time, NULL);
306 return 0;
309 #if 1
310 /* update the mount over time */
311 void readMountcurrentpos (void *p)
313 char result[32];
315 if(POWSW){
316 get_TemmaCurrentpos(result);
317 calcLST(result);
319 /* This is a temporary workaround to allow
320 clients with only one eq property to work */
321 currentRA=temmaRA;
322 currentDec=temmaDec;
324 /* again */
325 IEAddTimer (POLLMS, readMountcurrentpos, NULL);
328 #endif
330 static void connectMount () {
331 fprintf(stderr,"opening mount port %s\n",PortT->text);
332 if (power[0].s == ISS_ON){
333 if (Port.s != IPS_OK){
334 powSw.s = IPS_IDLE;
335 power[0].s = ISS_OFF;
337 IDSetSwitch (&powSw, "Port not set.");
338 return;
340 else {
341 if (TemmaConnect(PortT->text)==0){
342 IDSetText (&Port, "Port is opened.");
343 if( !get_TemmaVERSION(buffer)){
344 powSw.s = IPS_OK;
345 power[0].s = ISS_ON;
346 power[1].s = ISS_OFF;
347 snprintf(buffer2,sizeof( buffer2 ),"%s",buffer+4);
349 IDSetText(&TemmaVersion , "Temma version set");
350 TemmaVersionT->text = realloc(TemmaVersionT->text, strlen(buffer2)+1);
351 if (!TemmaVersionT->text){
352 fprintf(stderr,"Memory allocation error");
353 return;
355 IDSetSwitch (&powSw, "Mount is ready");
356 IDSetSwitch (&powSw, VERSION);
358 strcpy(TemmaVersionT->text, buffer2);
359 TemmaVersion.s = IPS_OK;
360 IDSetText (&TemmaVersion, NULL);
361 IDLog("%s", buffer2);
362 /* start timer to read mount coords */
363 IEAddTimer (POLLMS, readMountcurrentpos, NULL);
365 else {
366 powSw.s = IPS_IDLE;
367 power[0].s = ISS_OFF;
368 power[1].s = ISS_ON;
369 IDSetText(&Port , "Com error");
370 IDSetSwitch (&powSw, "Port not set.");
373 if(get_TemmaStandbyState(answer)){
374 IDSetSwitch (&RAmotorSw, "Error writing to port");
375 return;
378 else {
379 powSw.s = IPS_IDLE;
380 power[0].s = ISS_OFF;
381 power[1].s = ISS_ON;
383 IDSetSwitch (&powSw, "Failed to open port.");
389 static void disconnectMount () {
390 fprintf(stderr,"closing mount port %s\n",PortT->text);
391 if (power[1].s == ISS_ON){
392 if (Port.s != IPS_OK){
393 powSw.s = IPS_IDLE;
394 power[0].s = ISS_OFF;
396 IDSetSwitch (&powSw, "Port not set.");
397 return;
399 else {
400 TemmaDisconnect();
401 powSw.s = IPS_IDLE;
402 power[0].s = ISS_OFF;
404 IDSetSwitch (&powSw, "Port is closed.");
407 else {
408 fprintf(stderr, "Already disconnected \n");
412 int TemmaConnect(const char *device) {
413 fprintf(stderr, "Connecting to device %s\n", device);
415 if (openPort(device) < 0){
416 fprintf(stderr, "Error connecting to device %s\n", device);
417 return -1;
419 else{
420 return 0;
424 int TemmaDisconnect() {
425 fprintf(stderr, "Disconnected.\n");
426 close(fd);
428 return 0;
431 int set_CometTracking(int RArate, int DECrate){
432 #if 0
433 Set Comet Tracking
434 LM+/-99999,+/-9999
435 RA : Adjust Sidereal time by seconds per Day
437 DEC : Adjust DEC tracking by Minutes Per Day
438 valeur DEC min=-600 /max=+600 (+/-10 deg / jour)
440 Example:
441 LM+120,+30 would slow the RA speed by 86164/86284 and
442 the Dec would track at 30 Minutes a day.
443 To stop tracking either send a LM0,0 (or a PS
444 sauf erreur on constate en faite l inverse en RA
445 retour Vsideral => LM0,0 ou LM+0,+0
446 #endif
447 char local_buffer[16];
449 if (RArate<-21541){
450 RArate=-21541;
453 if (RArate>21541){
454 RArate=21541;
457 if (DECrate<-600){
458 DECrate=-600;
461 if (DECrate>600){
462 DECrate=600;
465 snprintf(local_buffer, sizeof( local_buffer ), "%+6d,%+5d", RArate, DECrate);
466 set_TemmaCometTracking(local_buffer);
468 return 0;
471 int TemmaabortSlew() {
472 if (portWrite("PS") < 0)
473 return -1;
475 return 0;
478 int do_TemmaGOTO() {
479 /* Temma Sync */
480 char command[16];
481 char sign;
482 double dec;
484 calcLST(buffer);
485 set_TemmaLST(buffer);
487 dec=fabs(currentDec);
488 if (currentDec>0){
489 sign='+';
491 else {
492 sign='-';
495 snprintf(buffer, sizeof(buffer),"%.2d%.2d%.2d%c%.2d%.2d%.1d",
496 (int)currentRA,(int)(currentRA*(double)60)%60,((int)(currentRA*(double)6000))%100,sign,
497 (int)dec,(int)(dec*(double)60)%60,((int)(dec*(double)600))%10);
498 fprintf(stderr,"Goto %s\n", buffer);
500 snprintf(command,14,"P%s",buffer);
501 buffer[14]=0;
502 fprintf(stderr,"Goto command:%s\n", command);
503 portWrite(command);
505 portRead(buffer,-1,TEMMA_TIMEOUT);
506 if(command[0]=='R'){
507 return 0;
509 else
510 return -1;
513 int extractRA(char *buf){
514 int r,h,m,s;
515 /*double dra;*/
517 r=atoi(buf);
518 h=r/10000;
519 m=r/100-100*h;
520 s=(r%100)*.6;
521 temmaRA=((double)h+((double)m + (double)s/60)/60);
522 IDSetNumber (&eqTemma, NULL);
523 /* fprintf(stderr,"extractRA: %s %d %d %d %d %lf\n",buf,r,h,m,s,dra);*/
524 return 0;
527 int extractDEC(char *buf){
528 int dec,d,m,s;
529 /*double ddec;*/
531 dec=atoi(buf+1);
532 d=dec/1000;
533 m=dec/10-100*d;
534 s=(dec%10)*6;
535 temmaDec=((double)d+((double)m + (double)s/60)/60);
536 if (*buf=='-')
537 temmaDec*=-1;
539 IDSetNumber (&eqTemma, NULL);
542 /* fprintf(stderr,"extractDEC: %s %d %d %d %d %lf\n",buf,dec,d,m,s,ddec);*/
543 return 0;
547 int get_TemmaCurrentpos(char *local_buffer){
548 char buf[16];
550 if (portWrite("E") < 0)
551 return -1;
553 if(portRead(local_buffer,-1,TEMMA_TIMEOUT)==SUCCESS){
554 if(strstr(local_buffer, "E")==local_buffer){
555 strncpy(buf,local_buffer+1,6);
556 buf[6]=0;
557 extractRA(buf);
559 strncpy(buf,local_buffer+7,6);
560 buf[6]=0;
561 extractDEC(buf);
562 return 0;
564 else {
565 return -1;
569 return 0;
572 int set_TemmaCurrentpos(void) {
573 /* Temma Sync */
574 char buf[16], sign;
575 double dec;
577 calcLST(buf);
578 set_TemmaLST(buf);
579 portWrite("Z");
580 calcLST(buf);
581 set_TemmaLST(buf);
583 dec=fabs(currentDec);
584 if (currentDec>0){
585 sign='+';
587 else {
588 sign='-';
591 sprintf(buffer,"%.2d%.2d%.2d%c%.2d%.2d%.1d",
592 (int)currentRA,(int)(currentRA*(double)60)%60,((int)(currentRA*(double)6000))%100,sign,
593 (int)dec,(int)(dec*(double)60)%60,((int)(dec*(double)600))%10);
594 fprintf(stderr,"sync to %s %f %f\n", buffer,currentRA,dec);
596 snprintf(buf, sizeof(buf), "D%s",buffer);
597 buf[13]=0;
598 portWrite(buf);
599 *buffer=0;
601 portRead(buffer,-1,TEMMA_TIMEOUT);
602 if(buffer[0]=='R'){
603 return 0;
605 else{
606 return -1;
610 int do_TemmaSLEW(char mode){
611 /*char command[16];*/
613 sprintf(buffer,"M%c",mode); /* see bit definition in Temmadriver.h */
615 if (portWrite(buffer) < 0)
616 return -1;
618 return 0;
621 int get_TemmaVERSION(char *local_buffer){
622 int err;
624 if ((err=portWrite("v")) < 0){
625 return err;
628 portRead(local_buffer,-1,TEMMA_TIMEOUT);
629 if(strstr(local_buffer, "ver")==local_buffer){
630 return 0;
632 else
633 return EREAD;
636 int get_TemmaGOTOstatus(char *local_buffer){
638 0 no ongoing goto
639 1 ongoing Goto
640 -1 error
642 if (portWrite("s") < 0)
643 return -1;
645 portRead(local_buffer,-1,TEMMA_TIMEOUT);
646 if(strstr(local_buffer, "s")==local_buffer){
647 return 0;
649 else
650 return -1;
653 int get_TemmaBOTHcorrspeed(char *local_buffer){
654 if (portWrite("lg") < 0)
655 return -1;
656 portRead(local_buffer,-1,TEMMA_TIMEOUT);
657 if(strstr(local_buffer, "lg")==local_buffer){
658 return 0;
660 else
661 return -1;
664 int get_TemmaDECcorrspeed(char *local_buffer){
665 if (portWrite("lb") < 0)
666 return -1;
667 portRead(local_buffer,-1,TEMMA_TIMEOUT);
668 if(strstr(local_buffer, "lb")==local_buffer){
669 return 0;
671 else
672 return -1;
675 int set_TemmaDECcorrspeed(char *local_buffer){
676 char command[16];
678 snprintf(command, 4, "LB%s",local_buffer);
680 if (portWrite(command) < 0)
681 return -1;
682 return 0;
685 int get_TemmaRAcorrspeed(char *local_buffer){
686 if (portWrite("la") < 0)
687 return -1;
689 portRead(local_buffer,-1,TEMMA_TIMEOUT);
690 if(strstr(local_buffer, "la")==local_buffer){
691 return 0;
693 else
694 return -1;
697 int set_TemmaRAcorrspeed(char *local_buffer){
698 char command[16];
700 snprintf(command, 4,"LA%s",local_buffer);
702 if (portWrite(command) < 0)
703 return -1;
704 return 0;
707 int get_TemmaLatitude(char *local_buffer){
708 if (portWrite("i") < 0)
709 return -1;
710 portRead(local_buffer,-1,TEMMA_TIMEOUT);
711 if(local_buffer[0]=='i'){
712 return 0;
714 else
715 return -1;
718 int set_TemmaLatitude(char *local_buffer){
719 char command[16];
720 double lat;
721 char sign;
723 lat=fabs(latitude);
724 if (latitude>0){
725 sign='+';
727 else {
728 sign='-';
731 sprintf(command,"I%c%.2d%.2d%.1d", sign,
732 (int)lat,
733 (int)(lat*(double)60)%60,
734 ((int)(lat*(double)600))%10);
736 if (portWrite(command) < 0)
737 return -1;
738 return 0;
741 int get_TemmaLST(char *local_buffer){
742 if (portWrite("g") < 0)
743 return -1;
745 portRead(local_buffer,-1,TEMMA_TIMEOUT);
746 if(local_buffer[0]=='g'){
747 return 0;
749 else
750 return -1;
754 int set_TemmaLST(char *local_buffer){
755 char command[16];
756 snprintf(command,7,"T%s",local_buffer);
758 if (portWrite(command) < 0)
759 return -1;
760 return 0;
764 int get_TemmaCometTracking(char *local_buffer){
765 if (portWrite("lm") < 0)
766 return -1;
767 portRead(local_buffer,-1,TEMMA_TIMEOUT);
768 if(strstr(local_buffer, "lm")==local_buffer){
769 return 0;
771 else
772 return -1;
775 int set_TemmaStandbyState(int on){
776 if (on){
777 return portWrite("STN-ON");
779 else{
780 return portWrite("STN-OFF");
782 return 0;
785 int get_TemmaStandbyState(unsigned char *local_buffer){
786 int nb;
787 int status;
789 if ((nb=portWrite("STN-COD")) < 0){
790 IDSetSwitch (&RAmotorSw, "I/O error when asking RAmotor status");
791 return -1;
794 if((status=portRead(local_buffer,-1,TEMMA_TIMEOUT)==SUCCESS)){
795 if(strstr(local_buffer, "stn")==local_buffer){
796 local_buffer[7]=0;
797 if (strstr(local_buffer,"on")){ /* stanby on */
798 RAmotorSw.s = IPS_OK;
799 RAmotor[0].s = ISS_OFF;
800 RAmotor[1].s = ISS_ON;
801 IDSetSwitch (&RAmotorSw, "RA motor is off.");
803 else{
804 if (strstr(local_buffer,"off")){ /* stanby off */
805 RAmotorSw.s = IPS_OK;
806 RAmotor[0].s = ISS_ON;
807 RAmotor[1].s = ISS_OFF;
808 IDSetSwitch (&RAmotorSw, "RA motor is on.");
810 else {
811 RAmotorSw.s = IPS_OK;
812 IDSetSwitch (&RAmotorSw, "I/O error when getting RAmotor status");
816 return 0;
818 if (status<=ETIMEOUT && status >=ECOMMAND){
819 IDSetSwitch(&RAmotorSw, "%s", errormes[ETIMEOUT - status]);
822 return -1;
825 int set_TemmaCometTracking(char *local_buffer){
826 char command[16];
828 snprintf(command,15,"LM%s",local_buffer);
829 if (portWrite(command) < 0)
830 return -1;
831 return 0;
834 int set_TemmaSolarRate(void){
835 if (portWrite("LK") < 0)
836 return -1;
837 return 0;
840 int set_TemmaStellarRate(void){
841 if (portWrite("LL") < 0)
842 return -1;
843 return 0;
847 int switch_Temmamountside(void){
848 if (portWrite("PT") < 0)
849 return -1;
850 return 0;
853 /**********************************************************************
854 * Comm
855 **********************************************************************/
857 int openPort(const char *portID) {
858 struct termios ttyOptions;
860 if ( (fd = open(portID, O_RDWR)) == -1)
861 return -1;
862 memset(&ttyOptions, 0, sizeof(ttyOptions));
863 tcgetattr(fd, &ttyOptions);
865 /* 8 bit, enable read */
866 ttyOptions.c_cflag |= CS8;
867 /* parity */
868 ttyOptions.c_cflag |= PARENB;
869 ttyOptions.c_cflag &= ~PARODD;
870 ttyOptions.c_cflag &= ~CSTOPB;
871 ttyOptions.c_cflag |= CRTSCTS;
873 /* set baud rate */
874 cfsetispeed(&ttyOptions, B19200);
875 cfsetospeed(&ttyOptions, B19200);
877 /* set input/output flags */
878 ttyOptions.c_iflag = IGNBRK;
880 /* Read at least one byte */
881 ttyOptions.c_cc[VMIN] = 1;
882 ttyOptions.c_cc[VTIME] = 5;
884 /* Misc. */
885 ttyOptions.c_lflag = 0;
886 ttyOptions.c_oflag = 0;
888 /* set attributes */
889 tcsetattr(fd, TCSANOW, &ttyOptions);
891 /* flush the channel */
892 tcflush(fd, TCIOFLUSH);
893 return (fd);
896 int portWrite(char * buf) {
897 int nbytes=strlen(buf); /*, totalBytesWritten;*/
898 int bytesWritten = 0;
899 /*int retry=10;*/
901 bytesWritten = write(fd, buf, nbytes);
902 bytesWritten += write(fd, "\r\n", 2);
903 /*fprintf(stderr,"portwrite :%d octets %s\n", bytesWritten, buf);*/
905 if (bytesWritten!=nbytes+2){
906 perror("write error: ");
907 IDLog("Error writing to port");
908 return EWRITE;
910 return (bytesWritten);
913 int portRead(char *buf, int nbytes, int timeout) {
915 A very basic finite state machine monitors
916 the bytes read ;
917 state 0 : read regular bytes
918 state 1 : just read a \n, waiting for a \r
919 state 2 : read a \n and a \r, command is over.
921 Not sure it is useful here but I use a more
922 sophisticated version of this with a GPS receiver
923 and it is robust and reliable
925 We return a null terminated string.
928 int bytesRead = 0, state=0, /*i=0,*/ current=0;
929 /*int totalBytesRead = 0;*/
930 int err;
932 if ( (err = TemmareadOut(timeout)) ){
933 switch (err){
934 case ETIMEOUT:
935 IDLog("Error: timeout while reading");
936 return err;
940 while (read(fd,buf+bytesRead,1)==1){
941 /* fprintf(stderr,"%c",buf[bytesRead]); */
942 fflush(NULL);
943 switch (state) {
944 case 0:
945 if(buf[bytesRead]==13)
946 state=1;
947 break;
949 case 1:
950 if(buf[bytesRead]==10)
951 state=2;
952 else
953 if(buf[bytesRead]==13)
954 state=1;
955 else
956 state=0;
957 break;
960 ++current;
962 if (state==2){
963 /*process(buf);*/
964 buf[bytesRead+1]=0;
965 state=current=0;
966 return SUCCESS;
969 bytesRead=current;
971 return state;
974 int TemmareadOut(int timeout) {
975 struct timeval tv;
976 fd_set readout;
977 int retval;
979 FD_ZERO(&readout);
980 FD_SET(fd, &readout);
982 /* wait for 'timeout' seconds */
983 tv.tv_sec = timeout;
984 tv.tv_usec = 0;
986 /* Wait till we have a change in the fd status */
987 retval = select (fd+1, &readout, NULL, NULL, &tv);
989 /* Return 0 on successful fd change */
990 if (retval > 0)
991 return 0;
992 /* Return -1 due to an error */
993 else if (retval == EREAD)
994 return retval;
995 /* Return -2 if time expires before anything interesting happens */
996 else {
997 return ETIMEOUT;