/*24.07.1999 : init_dmm liest nun zur Probe einen Meßwert und liefert -1 bei Fehlern.
               Das war nötig, weil der erste Wert nicht richtig gelesen wird, es fehlte
               manchmal die letzte Stelle der Einheit. 
               Übertragungsgeschwindigkeit 9660 Baud ergänzt.

  13.06.1999 : Übertragungsgeschwindigkeit als Parameter von init_dmm eingefügt.
  
  Erstellt im Mai 1999 */


#include <fcntl.h>
#include <sys/termios.h>
#include <sys/ioctl.h>
#include <stdio.h>

int init_dmm(const char * device, int speed) /* Funktion zum Initialisieren und Öffnen */
{                                 /* des Ports/Devices */
  int fd;
  char test[14];
  int modelines=0;
  struct termios settings;
  char baudrate[6];

/*Öffnen und Überprüfen des Filedeskriptors*/
  fd=open(device,O_RDWR|O_NOCTTY);
  if(fd==-1)
    {
      fprintf(stderr,"Das Device %s kann nicht geöffnet werden!\n",device);
      return(fd);
    }
/*Prüfe ob Filedeskriptor zu einem Terminal gehört*/
  if(!isatty(fd))
    {
      fprintf(stderr,"Das Device %s ist kein Terminal-Device !\n",device);
      return(-1);
    }
  

/*Setzen der Inputflags*/
  settings.c_iflag=   IGNBRK  /*Ignoriere BREAKS beim Input*/
                    | IGNPAR; /*Keine Parität*/

/*Setzen der Outputflags*/
  settings.c_oflag=0;         /*Keine besonderen Angaben nötig*/

/*Setzen der Controlflags*/
  settings.c_cflag= CS7       /*Setze sieben Bit pro Byte*/
                  | CSTOPB    /*Zwei Stopbits*/
                  | CREAD     /*Zeichen können von gelesen werden*/
                  | CLOCAL ;  /*Ignoriere Modemstatus, lokaler Anschluß*/

/*Setzen der lokalen Flags*/
  settings.c_lflag=0;         /*Keine besonderen Angaben nötig*/  

/*Festlegen der maximalen Zeit, welche beim Lesen gewartet werden soll*/
  settings.c_cc[VTIME]=30;  /*Geräte mit höheren Übertragungsgeschwindigkeiten */
                            /*können kleinere Werte erhalten */
                            /* z.B. ME-3850 : settings.c_cc[VTIME]=10 */
                            /*      ME-32   : settings.c_cc[VTIME]=30 */

/*Festlegen der minimalen Anzahl der zu lesenden Bytes -> Fall 3*/
  settings.c_cc[VMIN]=0;
  
/*Definieren der Übertragungsgeschwindigkeit */

  switch (speed) {
    case 9600:
              settings.c_cc[VTIME]=10;  /*Geräte mit höheren Übertragungsgeschwindigkeiten */
              settings.c_cc[VMIN]=0;
              if(cfsetspeed(&settings,B9600)!=0) /* A C H T U N G: Abhängig vom Meßgerät ! */
                {
                  fprintf(stderr,"Fehler beim Setzen der Übertragungsgeschwindigkeit auf %s !\n"
                   ,device);
                  return(-1);
                }
              break;

    case 1200:
              settings.c_cc[VTIME]=10;  /*Geräte mit höheren Übertragungsgeschwindigkeiten */
              settings.c_cc[VMIN]=0;
              if(cfsetspeed(&settings,B1200)!=0) /* A C H T U N G: Abhängig vom Meßgerät ! */
                {
                  fprintf(stderr,"Fehler beim Setzen der Übertragungsgeschwindigkeit auf %s !\n"
                   ,device);
                  return(-1);
                }
              break;
    case  600:
              settings.c_cc[VTIME]=30;  /*Geräte mit höheren Übertragungsgeschwindigkeiten */
              settings.c_cc[VMIN]=0;
              if(cfsetspeed(&settings,B600)!=0) /* A C H T U N G: Abhängig vom Meßgerät ! */
                {
                  fprintf(stderr,"Fehler beim Setzen der Übertragungsgeschwindigkeit auf %s !\n"
                   ,device);
                  return(-1);
                }
              break;
    default  : fprintf(stderr,"Unbekannte Übertragungsgeschwindigkeit!");exit();break;
  } 

/*Übertragung der Einstellungen an die Schnittstelle*/
  if(tcsetattr(fd,TCSANOW,&settings)==-1)
    {
      fprintf(stderr,"Fehler beim Setzen der Terminalattribute auf  %s !\n",device);
      return(-1);
    }

/*Lesen der IO-Control-Parameter*/
  if(ioctl(fd,TIOCMGET,&modelines)==-1)
    {
      fprintf(stderr,"Fehler bei ioctl TIOCMGET auf  %s!\n",device);
      return(-1);
    }

/*Setzen des RTS-Signals*/
  modelines &= ~TIOCM_RTS;
  if(ioctl(fd,TIOCMSET,&modelines)==-1) 
    {
      fprintf(stderr,"Fehler bei ioctl TIOCMSET auf %s !\n",device); 
      return(-1);
    }
/*Testen des Ports und der Kommunimation durch Lesen eines Meßwertes*/
  if (read_dmm(fd,test)==-1)
     {
      fprintf(stderr,"Fehler bei der Kommunikation mit dem Meßgerät an Port %s !\n",device);
      fprintf(stderr,"Ist das Meßgerät angeschlossen ?\n");
      return(-1);
     }
  sleep(2);
  return(fd);
} 


int read_dmm(int fd,char buf[14]) /* Funktion zum Lesen eines Meßwertes */
{
  int i;
  int nbyte;
    write(fd,"D\n",2); /*Schicke ein D ans Meßgerät*/
    i=-1;
    do{
       i++;
       nbyte=read(fd,&buf[i],1); /*Lies ein Zeichen*/
       if(nbyte!=1){             /*Gibt es kein Zeichen -> TIMEOUT*/
         fprintf(stderr,"TIMEOUT !\n");
         return (-1);
       }
    }
  while (((buf[i]!='\r')&&(nbyte==1))||(i<13)); /*Lies insgesamt 14 Zeichen*/
  return(1);
}

int close_dmm(int fd) /*Funktion zum Schließen des Devices*/
{
  return(close(fd));
}
