Max Users Manual

 

1.0 Introduction

2.0 Installation

3.0 How MAX works

4.0 Getting started

5 Timing and Trigger

6 Monitor Mode/DataQ Mode

7 Saving the Data

8 The Hardware Interface

9 The Linux Lab project and other links

10 The device Routines

11 Bugs and errors

Back to the Table of Contents

 

1 Introduction

The main concept of Max is based upon the cyclic structure of a data acquisition process. (see the Intro-page for more details) A certain number of device routines will be priodically called in an order defined by the user. Each of these cycles is called a "channel". During one cycle of device-function calls, perform in each channel, the device routine can take data from an external device and store the data. The measurement is finished after the given number of channels is finished. The device Functions are realized as small C-Functions with a standard header that have to be included in the programm. They are called via a vector of pointers to functions, which can be found in the Device Header file : devices.h. Each device is represented by four functions. An _init-function, a _pre_init-function, the _main-function and a _close-function, which will be periodically called at different times of the measurement process. (see chapter 3.3 for details.
Max has an internal database, initialized at startup through an initfile, which holds all device parameters for the measuremenent. The device routines have access to this database and can exchange data through this database. The user has access to this database as well via the graphical user Interface. This way he can modify the parameters of the measurement, also when the measurement is running.
The order of the devices called is given in the priority list, which the user can modify on the Main Window. Each "device" is assigned a number which determines the order in which it is called. If the priority is zero the device is not called at all.
Click on the link below to see a screenshot of the main widget. On the left of this widget you will see the buttons to control the measurement. Then follows the listbox showing the contents of the device parameter database. The right listbox is the priority database. It shows, in which oorder hte deives are called. A double click on the listbox items allows to alter the values in the line edit below the listbox. Each device can have several "channel" to store data into. A digitizing scope, for example, has several channels for data storage. The user can select how many channels to use an d wether he wants to plot the data or not. Each device-routine can take data and also store it in as many channels as neccessary. There exists an "enable" flag in the device-parameter database, that allows the user to toggle the status of a "channel", e.g. to switch it on or off. This is also done with a double click on the appropriate line in the listbox. the same is possible for the "plot" statemenent, which determines wether a dataset is supposed to be plotted or not. Click here Screenshots : The Main widget

2 Installation

2.1 Hardware and software requirements

Hardware :

Max runs on each LINUX machine with X11R6. I used to test it on a 486/133MHz PC with 32MB memory. The minimum speed of the machine depends mainly on the type of data acquisition process and measurement speed. Ususally a Pentium PC with at least 133MHz is recommended for a good performance of the GUI. If you take data with a frequency of 10Hz and only plot the data every few seconds, speed is no problem. For higher speeds a faster machine is required. Especially if Client and Server run on the same host(which is usually the case). Since Max relies on polling as the main data-acquistion process, it needs a lot of computing power for speeds > 100Hz, in order not to loose trigger events. A Pentium II with > 233 MHz should definetely do it, though. If you want to use KDE as your graphical fronted, don´t forget that it takes a lot of computing power and memory. I recommend at least 64 MB and a P233 or higher in that case, otherwise you may run into trouble when taking larger datasets. If you run the polld on a seperate host and use the networking capabilities of MAX, a small PC is enough. But you have to have an X-Server running before you start the polld. (This will be improved in later versions) For a really good performance of Max also for an application,which is  triggered around 50Hz, I recommend a PII233MHz and 64MB RAM+120MB SWAP.

Realtime Applications :

If realtime data acquisition is required,  the data acquistion routine must be seperated from the device-routine in the polld.  It has to run independently of Max in the background being triggered by an externel SIGNAl or interrupt.
An application could look like the following :
The <initialization> part of the  device routine starts the dataacqusition routine in the background, which sits there and waits for the interrupts. Then the main-device routine  in the polld just sits there and waits for a SIGNAL  (it may also try to read from a pipe) from the dataq-routine, to read out the data is has acquired in the meantime. The Data exchange may take place via sockets, pipes or, which is best in that case, shared memory segments with an IPC via semaphores.
The data is read out by the device function and stored as an array.

Software :

I have started to develop Max on a LINUX system with a kernel version higher than 2.0 and I have used gcc ver 2.7.2 to compile it. There are additional requirements for Max ver 2.0 : You can also compile it with egcs. I use the rpm package egcs-981208-1. There is a flag in the Makefile which you have to set according to the compiler you want to use. Check out the Makefile for details. Max uses classes from the STL (Standard Template library). That means you have to have installed the appropriate package. I use : libstdc++-2.8.0-14. Some distributions do not provide this package. If you use SUSE 6.0, as I do, get the package from the fileserver and install it with rpm -i package_name. To check wether the package is installed on your system, do a rpm -qa | grep libstd.You have to use Qt ver 1.42 or higher !
This version comes without any hardware drivers and only with dummy device modules, which generate artificial data for test purposes. Max was designed to be independent of any hardware drivers or interface cards, it does not perform any communication with any hardware or driver. Only the device -functions are supposed to access the hardware for data acqusition and measurement control. Hence, you can install any driver by including the appropritate filenames in the Makefile. We currently do use Max with the LINUX-Lab project GPIB driver and the Wiener CC16 CAMAC driver. If you want to use these, you can get a version with these drivers included together with the device modules already written for it from our ftp site.

2.2 The Qt-toolkit

Max uses the Qt-widget set from Troll Tech in Norway http://www.troll.no to implement the GUI. Qt is free, very fast and easy to use, thanks to Troll Tech.The version you should use is Qt ver 1.42 or higher! The older versions are not compatible with versions higher than 1.41 any more, due to some changes in the header files!

Hence, before you can use Max, download Qt from the adress given above. Do what they tell you there to install it (It's very easy) and make shure that you have the right paths in the max makefile (I use /usr/local/qt/include on Linux and /software/qt in the Institute's network ). (On a local system You should also install qt in /usr/local/qt.)

2.3 Installation

1) Download the latest version of Max from the ftp site into your home directory. (via anonymous ftp from the server of the Max-Born-Institute : ftp.mbi-berlin.de in the directory : /users/rosen/max20

2) Do a "gunzip max20.tar.gz" and untar it with the command : tar -xvf max20.tar.gz. This will create a new folder called Max20 in the directory you have copied the .tar file into.

3) Read the README file

4) Check that you have the Qt libs installed in /usr/local/qt and that the $QTDIR variable is set to this value. For more information about how set the paths can be found in the installation READMEs of Qt.

5) Check which compiler(s) is (are) installed on your system. Then set the compiler flag in the Makefile accordingly. It is _GCC_ for the GNU-C Compiler and _EGCS_ for egcs. Also make shure the libstdc++ package is installed.

6) Type "make clean", "make depend" and "make". That should do it to compile the demo version without any hardware drivers.

7) To include device drivers, check out the hardware section of this manual.

8) To test it, just type "max". This will start the client and the server on your localhost. If everything works, you should see the Main Window.

9) Errors : Sometimes you may get something like : "Couldn't find shared libraries libqt.so.1". This means, that your LD_LIBRARY_PATH variable is not set to the path, where the Qt-libs are found. Set it accordingly. Usually the path is set in the resource files in the homedirectory. Either in .cshrc, .tcshrc (in case you use the c-shell or the tc-shell) or .bshrc. The command īls -alī shows you all directory entries. There is an instruction about how to set the paths in the installation README of qt.

3.0 How Max works

Max is a client/server application. It consists out of two main parts :
The Client, that is the Main GUI, which is responsible for the user interaction and the Server, the polling deamon (polld), which performs the device function calls and sends the data to the client. The Interprocess Communicaton (IPC) takes place via sockets.
When starting Max, it first tries to start the polling deamon (the programm is calld polld) which opens the sockets and waits for connection. After a second the client is started and tries to connect to the server. If Max is started without any startup argument, it will automatically start the Server on the localhost.
If the user wants to start the server seperately or directly on a different host, he has to do the following :
  • Login in on the other host and start the polling deamon with the clients hostname as argument : polld client-hostname
  • Start Max on your host with the option -n and the hostname of the Server : max -n server-hostnameBoth ,Client and Server, will print out some information about the status of connection.

  •  

     

    3.1 The files

    For detailed information on the parts of the source code, which are relevant to the user, please check out the Class member list of the Source code browser.

    Check out the README file in the programm directory. It lists all the files of the packet. The files consists out of two sets. One for the Client, one for the Server.
     
     

    3.2 What happens during a measurement ?

    How does Max perform a measurement ?

    It has been said in the introduction, that the measurement is performed by calling a set of C-functions in a certain order, the priority. Furthermore it has been mentioned, that each "device" is represented by four functions.
    After the measurement is started, Max calls these device function periodically for each channel-number until the maximum number of integrations is reached. The function (or class), that performs the function calls is called "scheduler". (see the the C-Class browser for details on the function calls of the Scheduler class). The image on the right illustrates this timing cycle. Each color (red,blue and green) stands for one loop in the scheduler routine. The red color indicates a loop over the priorities (e.g. the device index), the blue color indictaes a loop over the integrations and the green color stands for the last, most important, loop over the channel numbers.

    If the users presses start, max sets channel and integrations to zero and priority to 1. It then takes a look in the priority database to see what device has the current priority 1.

    Before the actual measurement starts, the _init functions of all devices are called first in the order of their priorities. These device routines prepare the measurement, they do not take any data to store it. They simply reset some devices or do similar stuff. Never save any data in the _init routine.

    The pre-trigger routines are called during each cycle of integrations. (blue line in the graph) Hence, each time a datapoint is taken.They are used to reset each device again, before the main device function is called.

    The actual device functions, that perform the meausurement, are called in the same cycle of integrations but after the pre-trigger functions. These are the functions that can take data and hand in over to Max with the command void Scheduler::store(type ). The physical data saved with the see the void Scheduler::store(type) command is buffered and integrated automatically.

    After the maximum number of integrations is reached, the channel number is increased, integrations is set to zero again and n the cycle starts again until the stop button is pressed or the maximum channel number is reached. The device functions can always interrupt the measurement by returning FALSE to the scheduler.

    After the measurement is finished, the _close functions are called in the order given by their priorities, to close up all devices.

    As has been pointed out in the previous section, each device function consists out of four functions. The _init, the _pre, the _main and the _close functions. These functions have to be listed in the vector of functions pointers in the file device.h.

    3.3 Variable types and memory sizes

    The data measured can be stored as int, int *, double and double * with a special command : void Scheduler::store(type ). To obtain information on how to use this store command check out the Source Code Browser or take a look in the example devices file laser.cpp. The data will be stored in the internal database and integrated automatically during a cycle of integrations. This is also valid for arrays ! The array stored in the first cycle of integrations determines the length of the array. If the array size changes during one cycle of integrations it will either be truncated or padded with zeros. There is a limitation on the length of arrays and on the maximal numbers of variables, that can be stored per channel. These constants are set in the file definitions.hpp

    There is no limitation in channel numbers or integrations,. But be careful : Max does not check for a lack of memory !. Use the "top" command to check on memory usage.

    Max can handle as many devices functions as you like. The devices database can have any size,since max handles all data storage in dynamically allocated linked lists.

    The number of different data sets, that can be "stored" per channel is limited to 100 so far, but that number can be changed as well in the file : definitions.hpp (Check out the Source Code Browser for more information)

    3.4 The format of the saved data file

    The Save-Widgets, that pops up after the measurement is finished differentiates between "scalar" data, these are single integers or doubles, "Vector"-data, these are vectors and Images (Have not fully implemented that yet).

    Scalar data is saved to disk in two files in ASCII format. One is the .dat file, wich contains the data and one is a .txt file, which contains the dvice information and some additional text.The scalar data file contains rows and columns. The rows follow the channels number and there is a column for each variable stored in the experiment. That means, for example, if you store three values per channel and measure 1000 channels, the data file will contain 3 columns and 1000 rows. and looks as follows : (the text in italics is not saved, of course)
     
    channel 1st variable 2nd variable 3rd variable
    1 112 1212 1212
    2 23 23 2323
    3 23223 2323 2323
    4 2323 2323 2323
    5 2323 2323 2323

    The variables are seperated by a space character, so the file can be read with most data visualization programs like PAW, and ORIGIN or gnuplot and Xmgr.

    Array data is stored in ASCII format in a file with the extender .str as well together with a .txt file. The format of the arrays is a little bit different. Arrays are stored in a Matrix. The follwoing example shows the result of a measurement with a device that has "stored" 2 arrays per channel and measured 3 channels. This time, the first column is saved as index !
     
    index 1st array 2nd array 1st array 2nd array 1nd array 2nd array
    1 a11 a21 a11 a21 a11 a21
    2 a12 a22 a12 a22 a12 a22
    3 a13 a23 a13 a23 a13 a23

    4. Getting started

    4.1 The initfiles

    Max is configured via three initfiles. These files are read at startup. These are :

    The Main initfile initmax :

    ###### Main Initfile for Max #####
    # this file contains some initialization parameters for the programm
    # start max with your own initfile by providing
    # a new initfilename as start parameter
    # type max -f filename,
    # you personal initfile then contains your personal device combination for your
    # individual experiment
    
    integrations    1
    channels            2
    dev_file                initfile
    pr_file                 priority
    #data_file              data    # The data filename has the form _<"data_file">_.dat
    array_file      array   #Name of file to contain strings and arrays
    data_dir        ./      #data-directory path
    image_file      im
    The above listing shows a typical initfile. It contins the parameters integrations and Channels, which are most important for the program. Additionaly you find a list of filenames. These are the filenames of the other two initialization files, priority and initfile and the default filenames of the files to save the measured data in. On line is commented out with a "#" sign. This means that Max does not use a standard filename for this filetype, the data file. For more information of save-filenames see the Section "Save Data". You can start Max with the option "-f" to read in another file, than the deafult initfile named initfile.

    The Priority file : priority : This file contains a list of all devices, which are used in the programm :

            #
            # priority file for max (7/98)
            #
            # this file contains the device priorities
            # the priorities give the order in which the devices are called
            # all devices in the device vector (in devices.h) 
            # MUST have an entry here as well !!
            # (and they have to be in the same order)
            # zero means that the device is switched off
            # this file is read at startup
            # it's name is given in the main max-initfile "initmax"
            # see also the files : devices.h and laser.cpp
    
            laser 2  # this is a dummy device for test purposes
            adc   1  # dito 
            scope 0  # the priority of the device "scope"
    This file contains a list of all devices included in the programm together with a number, the so called priority. This number indicates in which order the devices are called during the measurement. In our example there are three devices included in the programm. (Included means, that there exist the C-Routines that form the device module and that they are compiled into the programm. Check out the "Getting Started-Section" for information on how to include new devices.) The device "adc" is called first, secondly the device "laser" is called, the device "scope" will not be called at all, it's priority is zero. There must be an entry here for each, that is listed in the device.h device-description header. Also the order in which the devices are given must be the same. The main initfile initmax The file described in the following is very important and the user will propably modifiy it the most. The initmax file contains a description off all device-parameters used by the device-modules. Max uses this file to initialize it's internal database with it. The user-defined device functions can access this database with the putvar and getvar functions to read device parameters for initialization purposes or to store data for the next run. The contents of this database are shown in the left listbox in the Main window. The user can modify this data by double clicking on the appropriate line in the listbox. The following listing shows a small excerpt from the initfile belonging to the device combination given in the priority-file above :
    ########################################################################
    # example devices initfile  for Max ver 2.x
    # August. 98
    # by Christian Rosen, rosen@mbi-berlin.de
    ##############################################################################
    # this file contains all device parameters that a device routine can access
    # these variables can be accessed on line by the user as well
    #
    # a new device declaration starts with the word device
    # active means that the device is called during all integrations cycles
    # store specifies a new data_set definition
    # if the device wants to store measured data, it HAS TO HAVE a store statement
    # the plot-options are optional, for default values see the file : definitions.hpp
    # Don't forget the PLOT and ENABLED flags. 
    # PLOT = TRUE -> data is plotted
    # ENABLE is checked by your device before data is stored
    # You can select the  data channels with it
    # 
    # see also the files  : 
    # devices.h       (-> the device vector and the device routine declarations are here)
    # laser.cpp       (-> here are all the device routines       )
    # priority        (-> the order of the devices is given here )
    # definitions.hpp (-> default definitions for plot windows   )
    #
    ###############################################################################
    
    device laser
            active
            double stepwidth 300
            store   channel1
    anything between store and the "begin" sign is discarded !
            {                               #this is a comment
                    PLOT            TRUE    #the PLOT and the ENABLED flag
                    ENABLED         TRUE    #default is FALSE
                    AUTOSCALE       TRUE    #Plot Window options
            }               
            double  phase           1
            double  steps           0.11
            int     ende                    55      
            int     scale           10
            store   channel_2
            { 
                    P_MIN_SIZE_X    100
                    ENABLED         FALSE   #this enables the chan
                    AUTOSCALE       TRUE
                    PLOT            TRUE
                    VGRIDLINES      TRUE
                    HGRIDLINES  FALSE
                    AUTOSCALE       TRUE
                    Y_UPPER_LIMIT   10
                    }                
            double  anfang          0.001
    device adc
            active
            store   channel_1
            {       
                    PLOT            TRUE
                    ENABLED         FALSE
                    AUTOSCALE       TRUE
            }       
            store   channel2
            {
                    PLOT            TRUE
                    ENABLED         FALSE
                    AUTOSCALE       TRUE
            }
            store channel3
            {
                    PLOT            TRUE
                    ENABLED         TRUE
                    AUTOSCALE       TRUE
                    Y_UPPER_LIMIT   500
            }
            int gate 100
            int gate2 140
            # fill in comments where you like
    This file contains two devices, "laser and "adc". Let's go line by line through the initfile given above : There is one section in this file for each "device". It starts with the word DEVICE and a device name. Anything that follows this statement will be associated with this device until a new DEVICE declaration is inserted. This line is followed by the word active. This command declares the device "laser" to an active device. That means that it is called during all cycles of integrations. If a device is not active, it is only called during the first integration. This is useful for a device that does not take data but simply sets some values. (A Voltage supply or a laser, that is scanned only once before the program integrates over several shots of the laser) Hence, each device, that stores values, e.g. takes data, has to be an active device.
    The next line is a parameter decleration. It means, that there is parameter, named "stepwith" of type double and that it will beinitialized to the value 300. You can insert a parameter declaration anywhere in the file, as long as it is not within a "STORE" statement. Each parameter is uniquely defined by the device name and the parameter name. It can therefore be accessed by the device functions with these two options. Any device function can access any parameter.
    Hence a data exchange between several devices is possible via some parameters in this database. The next line is a STORE statement. This statement tells Max that the device "laser" will measure data and store it. Each device that wants to take data has to have such a store statement. Max will check for missing store statements at runtime and stop program-execution as soon as it can not determine any more which device to identify with the data in memory. This happens, for example, if the user fogets the STORE statement in the initfile but does store measured data with the store command of the scheduler. The store command needs one prameter, the name of this channel. This name is used to name the plotwindow during the measurement.
    The STORE command start a special section in this file, in which all properties of this "channel" are declaired : The PLOT statements indicates wether the data stored in this channel is to be plotted on the screen.
    The ENABLED flag used to enable or disable a channel. The device routine can check the contents of this flag at runtime, to check the status. This feature enables the user to toggle selected channels at runtime. To do so he has to double click at the approprate line in the device-Parameter listbox. If STORE and ENABLED flag are not included they will be set to default values. The store sections allow you furthermore to configure the Plot-Windows. You can set options like AUTOSCALE, Y-SCALE and other things. to get a list of all Plot-Window Options check out the file : definitions.hpp in the Source Code Browser.
    The next lines contain some more parameter declarations and another STORE statement until there is a new device declaration of the device "adc", which contains elements similar to the one described above.

    4.2 The device functions

    The following programm code is an example of a device function, called "ADC". This routine is taken from the file laser.cpp. This device is a "dummy" device. It simulates a measurement and generates artificial data. The source code is well documented, so read it carefully. (Each important new function is marked bold type font.)

    Each device function takes the same arguments : List *device_data, Scheduler *parameters.These are pointers to the classes that handle the data storage. Just copy this line in your function.

    The device_data -> getvar (&var, var_name, device_name) and

    device_data-> putvar(value,var_name,device_name) functions handle the device Parameter data exchange with the List class. The parameters are simply device and variable name as specified in the initfile and a reference to the value (getvar) or simply the value itself(putvar)

    The parameters-> store(var_name) function, stores measured data in the database.

    The int parameters-> enabled(varname,device_name) function, checks wether this channel is enabled. If it returns TRUE, the value is stored.

    #include "list.hpp"   //this has to be included
    #include "sched.hpp"  //this has to be included
    #include "error.hpp"  //this has to be included//!The initfunction is called once before the measurement starts
    
    int adc_init(List *device_data, Scheduler *parameters) {
      printf("adc_init\n");
      return TRUE;  
    }
    //!this is the Pre_initfunction, it's called each time, before the integrastions cycle starts
    int adc_pre(List *device_data, Scheduler *parameters) {
        printf("adc_pre\n");
        return TRUE;
    }
    //! This is the main function of the \b device \b module adc. Here the data is taken.
    int adc(List *device_data, Scheduler *parameters) {
      int x;
      double messwert;
      double gate;
      double gate2;
      int enabled=1;
      printf("\nadc called ");
      result = device_data->getvar(&gate,"adc","gate"); //read a value from the database into the variable  gate
      enabled = device_data->enabled("adc","channel1"); //check if channel1 is enabled
      if(enabled) {
        printf("adc chan 1 is enabled \n");
        gate +=0.01;
        messwert = 1*sin(gate);
        result = device_data->putvar(gate,"adc","gate");
        parameters ->  store(messwert);
      }
      enabled = device_data->enabled("adc","channel2");  //check if channel is enabled
      if (enabled) {
        result = device_data -> getvar(&gate2,"adc","gate2");
        messwert = cos(gate2);
        gate2 += 0.01;
        result   = device_data -> putvar(gate2,"adc","gate2");
        parameters -> store(messwert);
      }
      enabled = device_data-> enabled("adc","channel3"); //check if channel3 is enabled
      if (enabled) {
        ind++;
        parameters -> store(ind);
      }
      return 1;
    }
    //! Close your device after the measurement is finished
    int adc_close(List *device_data, Scheduler *parameters) {
      printf("adc close.................\n");
      return TRUE;
    }
    /*************************************************************
     *   ERROR COMMANDS :
     * int Scheduler::error (char *formatstr,....)
     *   -> compose your individual errormessage
     * int Scheduler::error (char *ERRMSG,char *NAME)
     *   -> uses standard error messages from error.hpp
     * they return TRUE if the user wants to continue
     * they return FALSE in case of abort
     *  -> abort the measurement by returning FALSE from the device_function
     *************************************************************/
    Take a look at the Source Code Browser for more information about the Scheduler class and the commands accesible by the device function.
    The device function returns TRUE if the measurement was successful. It returns FALSE and the measurement will be stopped. This is the case after an error has occured. The user will the be prompted to save the data.
    There also exists an error function :
    This function call is used to inform the user about "trouble" in the device-routine. In case of error (like a Timeout, for example) the device function can call this routine to create a little warning message on the screen. The user is then prompted to abort or to continue the measurement. The error function returns accordingly. There are two kinds of error functions :
    One uses a standard set of error definitions. (see error.hpp for details). The other call enables the user to pass a format string to the error-widget, to show individual error messages and parameters.

    4.3 The devices.h device-header file

    This file contains the definitions of all device routines. Of course, you don't have to put them all here, but you should still do so, since it they are all in one place here and you have a better overview. This file contains another very important definition, this is the device-vector. The following piece of code, shows what it looks like :
    int laser_init (List *, Scheduler *);  //header declarations
    int laser      (List *, Scheduler *);
    int laser_pre  (List *, Scheduler *);
    int laser_close(List *, Scheduler *);
    
    /****************************************
     *NUMBER_DEVICES contains the number of
     *devices in the Function_List vector
     *MAKE SHURE IT IS CORRECT !!!!!
     *****************************************/
    #define NUMBER_DEVICES 3  //increase this value if you add a new device !!
    
    int (*Function_List      [NUMBER_DEVICES]) (List *, Scheduler *)  = {laser,adc,scope};
    int (*Pre_Function_List  [NUMBER_DEVICES]) (List *, Scheduler *)  = {laser_pre,adc_pre,scope_pre};
    int (*Init_Function_List [NUMBER_DEVICES]) (List *, Scheduler *)  = {laser_init,adc_init,scope_init};
    int (*Close_Function_List[NUMBER_DEVICES]) (List *, Scheduler *)  = {laser_close,adc_close,scope_close};
    Again we use a file from the example. Hence it contains descriptions about the three devices "scope","adc" and "laser". The first four lines are one set of header declarations. Remember, each device consists out four routines! The definition NUMBER_DEVICES simply gives the length of the following device vector. Increase this number if you add a new device. The Function_List-Vector is a vector to a pointer of functions, the device functions. These are functions that receive a pointer to the List and Scheduler class as arguments and return an integer. To implement a new device, you have to add the names of the new device functions to this vector.

    4.4 How to implement new device functions
    To implement a new device, you have to the following :

    1. Write a C-Module according to the declarations in Section 4.2 of this manual.
    2. Add an entry in the Device-Function vector in the file device.h.(See section 4.3 of this manual)
    3. Add an entry for your device in the priority-file. Remember : The devices have to be in the same order here as in the device-vector.Otherwise the devices will be called in the wrong order.
    4. Set up the device parameter database. Add a DEVICE my-device-name-section. Add active and store statements. Don't forget the enabled and plot statements
    5. Add you the filename of your device file to the Makefile in the section DEVICE.
    6. Type "make" to compile everything, that should do it.
    There are no hardware drivers included in the example. The user has to take care of the implementation of specific drivers himself. That's basically all you have to do to get a new device-routine running.

    5.0 Timing and Trigger

    5.1 External Timing

    No data acqusition process runs without a trigger. There has to be a device that tells you when to start. In most cases(if you don't need high speed data acqusition) polling is used. Polling means that the computer periodically checks a device if the trigger is present. If so, the process starts to read out the data. Otherwise he continues polling. Also Max uses polling, but you have to implement that yourself. There has to be a plling routine in the device function, which waits until the trigger is present and it can continue to read out the data. but, and that is the advantage of hte cyclic function calls, it is sufficient, if only the device called first, e.g. the device with priority 1, does the polling. (It has to be an active device, of couse.) This way you can easily realize a central trigger for all devices in the loop. Max is a multitasking application. The polling takes place in a routine running in a seperate process than the Main Event Loop of the Graphical user interface. So the Windows won't "hang" while you device polls and polls and polls...

    5.2 Internal Timing

    You can also select "internal timing". If you do that, max will trigger the measurement by an internal timer. You can set the trigger intervalls in the Main Window. This is useful in monitor mode, which is described in the follwing chapter. If you have selected "internal timer", it is not useful to use a plling device in your device vector, of course! You shoud switch it of if you measure in thsi mode.

    6.0 Monitor Mode/DataQ Mode

    The Dataq Mode (data acquisition mode) is the regular mode of operation.
    The Monitor Mode is special, though. If you run Max in Monitor Mode it does not store any data. It will only be plotted on the screen for monitoring purposes. It does this forever. The channel number criteria is not valid anymore for aborting the measurement. You have to press the STOP button. This feature is useful for simply monitoring a signal while doing some adjustments at the experimental setup. It is especially useful in combination with the internal trigger mode.

    7.0 Saving the data

    After the measurement is finished, a save Widget pops up and prompts the user for filenames. Depending on what kind of data the user has taken, it will offer a filename for the file that contains the scalar data and a filename for the file to save the vector data into. The filename always consists out of a name given in the main-initfile and some text specified by the user. The extender for files that contain scalar data, is .dat, the extender of files containing vector data is : str. The data will be saved in ASCII format, it should be readable by most data analysis programs. If you choose the "text" field, you will see a list of all device parameters of the devices used. You can add some personal comments about the measurement here. This file will be saved with a .txt extender.

    8.0 The Hardware Interfaces

    The LINUX-driver for the National Instruments GPIB-card, which we currently use, and all informations about the Linux-lab project can be retrieved from the following adress : ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/IEEE488. Here you can also find all informations on installing the GPIB driver. CAN-Bus interface can be found under : ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/IEEE488

    9.0 The LINUX-Lab project on other links...

    Here are some useful links on LINUX :

    - The LINUX Lab-project

    - The official LINUX homepage

    - LINUX HQ, for Kernel Hackers but it also contains a lot of good documentation

    - The LINUX journal

    - The LINUX journal LINUX resources...

    - The LINUX documentation project and a lot of links...

    10.0 Bugs and errors

    As usual, there are still some things to be fixed : 1) Max relies on a proper initialization of the database. It checks for consistency of the initfiles but does not find all possible spelling or syntax errors. 2) The polld crashes if the device-module´s C-Code contains errors. The client then receives a SIGPIPE-signal and terminates as well. Nevertheless, it may happen that either one, client or server, is still alive and running in the background after the application has abnormally terminated. Hence, check with top command wether the polld or max are still alive before starting max again. Starting max again with a polld-deamon already running in the background from a previous session will fail. 3) Max does not check for free memory. If your memory and swap space run full, it´s over !!!! 4) The plotroutine still has some minor bugs, did not have time to fix them yet. 5) The continue button causes the polld to crash sometimes - > don't use it ! 

    Comments to :

    Stefan Gerlach