LCOV - code coverage report
Current view: top level - src - device_driver.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 165 0
Test Date: 2025-11-11 10:26:08 Functions: 0.0 % 2 0

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         device_driver.c
       4              :   Created by:   Stefan Ritt
       5              : 
       6              :   Contents:     The system part of the MIDAS frontend.
       7              : 
       8              : \********************************************************************/
       9              : 
      10              : #include <stdio.h>
      11              : #include <assert.h>
      12              : #include "midas.h"
      13              : #include "msystem.h"
      14              : 
      15            0 : static int sc_thread(void *info)
      16              : {
      17            0 :    DEVICE_DRIVER *device_drv = (DEVICE_DRIVER*)info;
      18              :    int i, status, cmd;
      19            0 :    int current_channel = 0;
      20            0 :    int current_priority_channel = 0;
      21              :    float value;
      22              :    int *last_update;
      23              :    unsigned int current_time;
      24              :    DWORD last_time;
      25              : 
      26            0 :    ss_thread_set_name(std::string("SC:")+ *device_drv->pequipment_name);
      27              : 
      28            0 :    last_update = (int*)calloc(device_drv->channels, sizeof(int));
      29            0 :    for (i=0 ; i<device_drv->channels ; i++)
      30            0 :       last_update[i] = ss_millitime() - 20000;
      31            0 :    last_time = ss_millitime();
      32              : 
      33              :    // call CMD_START of device driver
      34            0 :    device_drv->dd(CMD_START, device_drv->dd_info, 0, NULL);
      35              : 
      36              :    // initialize setting to NAN in order not to trigger an immediate write
      37            0 :    for (i = 0; i < device_drv->channels; i++)
      38            0 :       device_drv->mt_buffer->channel[i].variable[CMD_SET] = (float) ss_nan();
      39              : 
      40            0 :    int skip = 0;
      41              :    do {
      42              : 
      43              :       // only operate if enabled
      44            0 :       if (device_drv->pequipment->enabled) {
      45              : 
      46              :          /* read one channel from device, skip if time limit is set */
      47              : 
      48              :          /* limit data rate if defined in equipment list */
      49            0 :          if (device_drv->pequipment && device_drv->pequipment->event_limit && current_channel == 0) {
      50            0 :             if (ss_millitime() - last_time < (DWORD) device_drv->pequipment->event_limit) {
      51            0 :                skip = 1;
      52              :             } else {
      53            0 :                skip = 0;
      54            0 :                last_time = ss_millitime();
      55              :             }
      56              :          }
      57              : 
      58            0 :          if (!skip) {
      59            0 :             for (cmd = CMD_GET_FIRST; cmd <= CMD_GET_LAST; cmd++) {
      60            0 :                value = (float) ss_nan();
      61            0 :                status = device_drv->dd(cmd, device_drv->dd_info, current_channel, &value);
      62              : 
      63            0 :                ss_mutex_wait_for(device_drv->mutex, 1000);
      64            0 :                device_drv->mt_buffer->channel[current_channel].variable[cmd] = value;
      65            0 :                device_drv->mt_buffer->status = status;
      66            0 :                ss_mutex_release(device_drv->mutex);
      67              :             }
      68            0 :             device_drv->mt_buffer->channel[current_channel].n_read++;
      69              :          }
      70              : 
      71              :          /* switch to next channel in next loop */
      72            0 :          current_channel = (current_channel + 1) % device_drv->channels;
      73              : 
      74              :          /* check for priority channel */
      75            0 :          if (device_drv->flags & DF_PRIORITY_READ) {
      76            0 :             current_time = ss_millitime();
      77            0 :             i = (current_priority_channel + 1) % device_drv->channels;
      78            0 :             while (!(current_time - last_update[i] < 10000)) {
      79            0 :                i = (i + 1) % device_drv->channels;
      80            0 :                if (i == current_priority_channel) {
      81              :                   /* non found, so finish */
      82            0 :                   break;
      83              :                }
      84              :             }
      85              : 
      86              :             /* updated channel found, so read it additionally */
      87            0 :             if (current_time - last_update[i] < 10000) {
      88            0 :                current_priority_channel = i;
      89              : 
      90            0 :                for (cmd = CMD_GET_FIRST; cmd <= CMD_GET_LAST; cmd++) {
      91            0 :                   status = device_drv->dd(cmd, device_drv->dd_info, i, &value);
      92              : 
      93            0 :                   ss_mutex_wait_for(device_drv->mutex, 1000);
      94            0 :                   device_drv->mt_buffer->channel[i].variable[cmd] = value;
      95            0 :                   device_drv->mt_buffer->status = status;
      96            0 :                   ss_mutex_release(device_drv->mutex);
      97              :                }
      98              :             }
      99              :          }
     100              : 
     101              :          // copy potential set value to get/get_demand buffers to avoid old value there to be copied to ODB
     102            0 :          for (i = 0; i < device_drv->channels; i++) {
     103              : 
     104            0 :             for (cmd = CMD_SET_FIRST; cmd <= CMD_SET_LAST; cmd++) {
     105            0 :                if (!ss_isnan(device_drv->mt_buffer->channel[i].variable[cmd])) {
     106            0 :                   ss_mutex_wait_for(device_drv->mutex, 1000);
     107            0 :                   value = device_drv->mt_buffer->channel[i].variable[cmd];
     108            0 :                   ss_mutex_release(device_drv->mutex);
     109              : 
     110            0 :                   if (cmd == CMD_SET) {
     111            0 :                      ss_mutex_wait_for(device_drv->mutex, 1000);
     112            0 :                      device_drv->mt_buffer->channel[i].variable[CMD_GET] = value;
     113            0 :                      device_drv->mt_buffer->channel[i].variable[CMD_GET_DEMAND] = value;
     114            0 :                      ss_mutex_release(device_drv->mutex);
     115              :                   }
     116              :                }
     117              :             }
     118              :          }
     119              : 
     120              :          /* check if anything to write to device */
     121            0 :          for (i = 0; i < device_drv->channels; i++) {
     122              : 
     123            0 :             for (cmd = CMD_SET_FIRST; cmd <= CMD_SET_LAST; cmd++) {
     124            0 :                if (!ss_isnan(device_drv->mt_buffer->channel[i].variable[cmd])) {
     125            0 :                   ss_mutex_wait_for(device_drv->mutex, 1000);
     126            0 :                   value = device_drv->mt_buffer->channel[i].variable[cmd];
     127            0 :                   device_drv->mt_buffer->channel[i].variable[cmd] = (float) ss_nan();
     128            0 :                   ss_mutex_release(device_drv->mutex);
     129              : 
     130            0 :                   status = device_drv->dd(cmd, device_drv->dd_info, i, value);
     131            0 :                   device_drv->mt_buffer->status = status;
     132            0 :                   if (cmd == CMD_SET)
     133            0 :                      last_update[i] = ss_millitime();
     134              :                }
     135              :             }
     136              :          }
     137              :       } // enabled
     138              : 
     139            0 :       ss_sleep(10); // don't eat all CPU
     140              : 
     141            0 :    } while (device_drv->stop_thread == 0);
     142              : 
     143            0 :    free(last_update);
     144              : 
     145              :    /* signal stopped thread */
     146            0 :    device_drv->stop_thread = 2;
     147              : 
     148            0 :    return SUCCESS;
     149              : }
     150              : 
     151              : /*------------------------------------------------------------------*/
     152              : 
     153            0 : INT device_driver(DEVICE_DRIVER * device_drv, INT cmd, ...)
     154              : {
     155              :    va_list argptr;
     156              :    HNDLE hKey;
     157              :    INT channel, status, i, j;
     158              :    float value, *pvalue;
     159              :    char *name, *label;
     160              : 
     161            0 :    va_start(argptr, cmd);
     162            0 :    status = FE_SUCCESS;
     163              : 
     164              :    /* don't execute command if driver is disabled */
     165            0 :    if (!device_drv->enabled)
     166            0 :       return FE_PARTIALLY_DISABLED;
     167              :    
     168            0 :    switch (cmd) {
     169            0 :    case CMD_INIT:
     170            0 :       hKey = va_arg(argptr, HNDLE);
     171              : 
     172            0 :       if (device_drv->flags & DF_MULTITHREAD) {
     173            0 :          status = device_drv->dd(CMD_INIT, hKey, &device_drv->dd_info,
     174              :                                     device_drv->channels, device_drv->flags,
     175              :                                     device_drv->bd);
     176              : 
     177            0 :          if (status == FE_SUCCESS && (device_drv->flags & DF_MULTITHREAD)) {
     178              :             /* create inter-thread data exchange buffers */
     179            0 :             device_drv->mt_buffer = (DD_MT_BUFFER *) calloc(1, sizeof(DD_MT_BUFFER));
     180            0 :             device_drv->mt_buffer->n_channels = device_drv->channels;
     181            0 :             device_drv->mt_buffer->channel = (DD_MT_CHANNEL *) calloc(device_drv->channels, sizeof(DD_MT_CHANNEL));
     182            0 :             assert(device_drv->mt_buffer->channel);
     183              : 
     184              :             /* initialize n_read for all channels */
     185            0 :             for (i=0 ; i<device_drv->channels ; i++)
     186            0 :                device_drv->mt_buffer->channel[i].n_read = 0;
     187              : 
     188              :             /* set all get values to NaN */
     189            0 :             for (i=0 ; i<device_drv->channels ; i++)
     190            0 :                for (j=CMD_GET_FIRST ; j<=CMD_GET_LAST ; j++)
     191            0 :                   device_drv->mt_buffer->channel[i].variable[j] = (float) ss_nan();
     192              : 
     193              :             /* set all set values to NaN */
     194            0 :             for (i=0 ; i<device_drv->channels ; i++)
     195            0 :                for (j=CMD_SET_FIRST ; j<=CMD_SET_LAST ; j++)
     196            0 :                   device_drv->mt_buffer->channel[i].variable[j] = (float)ss_nan();
     197              : 
     198              :             /* get default names for this driver already now */
     199            0 :             for (i = 0; i < device_drv->channels; i++) {
     200            0 :                device_drv->dd(CMD_GET_LABEL, device_drv->dd_info, i,
     201            0 :                               device_drv->mt_buffer->channel[i].label);
     202              :             }
     203              :             /* create semaphore */
     204            0 :             status = ss_mutex_create(&device_drv->mutex, FALSE);
     205            0 :             if (status != SS_CREATED && status != SS_SUCCESS)
     206            0 :                return FE_ERR_DRIVER;
     207            0 :             status = FE_SUCCESS;
     208              :          }
     209              :       } else {
     210            0 :          status = device_drv->dd(CMD_INIT, hKey, &device_drv->dd_info,
     211              :                                     device_drv->channels, device_drv->flags,
     212              :                                     device_drv->bd);
     213              :       }
     214            0 :       break;
     215              : 
     216            0 :    case CMD_START:
     217            0 :       if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL) {
     218              :          /* create dedicated thread for this device */
     219            0 :          device_drv->mt_buffer->thread_id = ss_thread_create(sc_thread, device_drv);
     220              :       }
     221            0 :       break;
     222              : 
     223            0 :    case CMD_CLOSE:
     224              :       /* signal all threads to stop */
     225            0 :       if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL)
     226            0 :          device_drv->stop_thread = 1;
     227            0 :       break;
     228              : 
     229            0 :    case CMD_STOP:
     230            0 :       if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL) {
     231            0 :          if (device_drv->stop_thread == 0)
     232            0 :             device_drv->stop_thread = 1;
     233              : 
     234              :          /* wait for max. 10 seconds until thread has gracefully stopped */
     235            0 :          for (i = 0; i < 1000; i++) {
     236            0 :             if (device_drv->stop_thread == 2)
     237            0 :                break;
     238            0 :             ss_sleep(10);
     239              :          }
     240              : 
     241              :          /* if timeout expired, kill thread */
     242            0 :          if (i == 1000)
     243            0 :             ss_thread_kill(device_drv->mt_buffer->thread_id);
     244              : 
     245            0 :          ss_mutex_delete(device_drv->mutex);
     246            0 :          free(device_drv->mt_buffer->channel);
     247            0 :          free(device_drv->mt_buffer);
     248              :       }
     249            0 :       break;
     250              : 
     251            0 :    case CMD_EXIT:
     252            0 :       status = device_drv->dd(CMD_EXIT, device_drv->dd_info);
     253            0 :       break;
     254              : 
     255            0 :    case CMD_SET_LABEL:
     256            0 :       channel = va_arg(argptr, INT);
     257            0 :       label = va_arg(argptr, char *);
     258            0 :       status = device_drv->dd(CMD_SET_LABEL, device_drv->dd_info, channel, label);
     259            0 :       break;
     260              : 
     261            0 :    case CMD_GET_LABEL:
     262            0 :       channel = va_arg(argptr, INT);
     263            0 :       name = va_arg(argptr, char *);
     264            0 :       status = device_drv->dd(CMD_GET_LABEL, device_drv->dd_info, channel, name);
     265            0 :       break;
     266              : 
     267            0 :    default:
     268              : 
     269            0 :       if (cmd >= CMD_SET_FIRST && cmd <= CMD_SET_LAST) {
     270              : 
     271              :          /* transfer data to sc_thread for SET commands */
     272            0 :          channel = va_arg(argptr, INT);
     273            0 :          value = (float) va_arg(argptr, double);        // floats are passed as double
     274            0 :          if (device_drv->flags & DF_MULTITHREAD) {
     275            0 :             ss_mutex_wait_for(device_drv->mutex, 1000);
     276            0 :             device_drv->mt_buffer->channel[channel].variable[cmd] = value;
     277            0 :             status = device_drv->mt_buffer->status;
     278            0 :             ss_mutex_release(device_drv->mutex);
     279              :          } else {
     280            0 :             status = device_drv->dd(cmd, device_drv->dd_info, channel, value);
     281              :          }
     282              : 
     283            0 :       } else if (cmd >= CMD_GET_FIRST && cmd <= CMD_GET_LAST) {
     284              : 
     285              :          /* transfer data from sc_thread for GET commands */
     286            0 :          channel = va_arg(argptr, INT);
     287            0 :          pvalue = va_arg(argptr, float *);
     288            0 :          if (device_drv->flags & DF_MULTITHREAD) {
     289            0 :             ss_mutex_wait_for(device_drv->mutex, 1000);
     290            0 :             *pvalue = device_drv->mt_buffer->channel[channel].variable[cmd];
     291            0 :             status = device_drv->mt_buffer->status;
     292            0 :             if (device_drv->mt_buffer->channel[channel].n_read < 1)
     293            0 :                status = FE_NOT_YET_READ;
     294            0 :             ss_mutex_release(device_drv->mutex);
     295              :          } else
     296            0 :             status = device_drv->dd(cmd, device_drv->dd_info, channel, pvalue);
     297              : 
     298              :       } else {
     299              : 
     300              :          /* all remaining commands which are passed directly to the device driver */
     301            0 :          channel = va_arg(argptr, INT);
     302            0 :          pvalue = va_arg(argptr, float *);
     303            0 :          status = device_drv->dd(cmd, device_drv->dd_info, channel, pvalue);
     304              :       }
     305              : 
     306            0 :       break;
     307              :    }
     308              : 
     309            0 :    va_end(argptr);
     310            0 :    return status;
     311              : }
     312              : 
     313              : /* emacs
     314              :  * Local Variables:
     315              :  * tab-width: 8
     316              :  * c-basic-offset: 3
     317              :  * indent-tabs-mode: nil
     318              :  * End:
     319              :  */
        

Generated by: LCOV version 2.0-1