LCOV - code coverage report
Current view: top level - drivers/class - cd_ivc32.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 412 0
Test Date: 2025-11-11 10:26:08 Functions: 0.0 % 18 0

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         cd_ivc32.c
       4              :   Created by:   Pierre-Andre Amaudruz
       5              : 
       6              :   Contents:     MSCB IVC32 for the LiXe Intermediate HV control
       7              :                 Refer for documentation to:
       8              :                 http://daq-plone.triumf.ca/HR/PERIPHERALS/IVC32.pdf 
       9              : 
      10              :   $Id$
      11              : \********************************************************************/
      12              : 
      13              : #include <stdio.h>
      14              : #include <math.h>
      15              : #include <string.h> // memcpy()
      16              : #include <assert.h>
      17              : #include "midas.h"
      18              : 
      19              : typedef struct {
      20              : 
      21              :    /* ODB keys */
      22              :    HNDLE hKeyRoot, hKeyDemand, hKeyMeasured, hKeyCurrent;
      23              : 
      24              :    /* globals */
      25              :    INT num_channels;
      26              :    INT format;
      27              :    DWORD last_update;
      28              :    INT last_channel;
      29              :    INT last_channel_updated;
      30              : 
      31              :    /* items in /Variables record */
      32              :    char *names;
      33              :    float *demand;
      34              :    float *measured;
      35              :    float *current;
      36              : 
      37              :    /* items in /Settings */
      38              :    float *update_threshold;
      39              :    float *update_threshold_current;
      40              :    float *voltage_limit;
      41              :    float *current_limit;
      42              :    float *ramp_step;   //Ramp Step in Volts WORD 
      43              :    float *step_time; // Step Time in millisecond WORD
      44              :    float *trip_time;
      45              : 
      46              :    /* mirror arrays */
      47              :    float *demand_mirror;
      48              :    float *measured_mirror;
      49              :    float *current_mirror;
      50              :    DWORD *last_change;
      51              : 
      52              :    DEVICE_DRIVER **driver;
      53              :    INT *channel_offset;
      54              :    void **dd_info;
      55              : 
      56              : } HV_INFO;
      57              : 
      58              : #ifndef abs
      59              : #define abs(a) (((a) < 0)   ? -(a) : (a))
      60              : #endif
      61              : 
      62              : /*------------------------------------------------------------------*/
      63              : 
      64            0 : static void free_mem(HV_INFO * hv_info)
      65              : {
      66            0 :    free(hv_info->names);
      67            0 :    free(hv_info->demand);
      68            0 :    free(hv_info->measured);
      69            0 :    free(hv_info->current);
      70              : 
      71            0 :    free(hv_info->update_threshold);
      72            0 :    free(hv_info->update_threshold_current);
      73            0 :    free(hv_info->voltage_limit);
      74            0 :    free(hv_info->current_limit);
      75            0 :    free(hv_info->ramp_step);
      76            0 :    free(hv_info->step_time);
      77            0 :    free(hv_info->trip_time);
      78              : 
      79            0 :    free(hv_info->demand_mirror);
      80            0 :    free(hv_info->measured_mirror);
      81            0 :    free(hv_info->current_mirror);
      82            0 :    free(hv_info->last_change);
      83              : 
      84            0 :    free(hv_info->dd_info);
      85            0 :    free(hv_info->channel_offset);
      86            0 :    free(hv_info->driver);
      87              : 
      88            0 :    free(hv_info);
      89            0 : }
      90              : 
      91              : /*----------------------------------------------------------------------------*/
      92              : 
      93            0 : INT ivc32_start(EQUIPMENT * pequipment)
      94              : {
      95              :    INT i;
      96              : 
      97              :    /* call start method of device drivers */
      98            0 :    for (i = 0; pequipment->driver[i].dd != NULL ; i++)
      99            0 :       if (pequipment->driver[i].flags & DF_MULTITHREAD) {
     100            0 :          pequipment->driver[i].pequipment = &pequipment->info;
     101            0 :          device_driver(&pequipment->driver[i], CMD_START);
     102              :       }
     103              : 
     104            0 :    return FE_SUCCESS;
     105              : }
     106              : 
     107              : /*----------------------------------------------------------------------------*/
     108              : 
     109            0 : INT ivc32_stop(EQUIPMENT * pequipment)
     110              : {
     111              :    INT i;
     112              : 
     113              :    /* call close method of device drivers */
     114            0 :    for (i = 0; pequipment->driver[i].dd != NULL ; i++)
     115            0 :       if (pequipment->driver[i].flags & DF_MULTITHREAD)
     116            0 :          device_driver(&pequipment->driver[i], CMD_STOP);
     117              : 
     118            0 :    return FE_SUCCESS;
     119              : }
     120              : 
     121              : /*------------------------------------------------------------------*/
     122              : 
     123            0 : INT ivc32_read(EQUIPMENT * pequipment, int channel)
     124              : {
     125              :    int i;
     126            0 :    int status = 0;
     127              :    float max_diff;
     128              :    DWORD act_time, min_time;
     129              :    BOOL changed;
     130              :    HV_INFO *hv_info;
     131              :    HNDLE hDB;
     132              : 
     133            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     134            0 :    cm_get_experiment_database(&hDB, NULL);
     135              : 
     136              :    /* if driver is multi-threaded, read all channels at once */
     137            0 :    for (i=0 ; i < hv_info->num_channels ; i++) {
     138            0 :       if (hv_info->driver[i]->flags & DF_MULTITHREAD) {
     139            0 :          status = device_driver(hv_info->driver[i], CMD_GET,
     140            0 :                                 i - hv_info->channel_offset[i],
     141            0 :                                 &hv_info->measured[i]);
     142            0 :          status = device_driver(hv_info->driver[i], CMD_GET_CURRENT,
     143            0 :                                 i - hv_info->channel_offset[i],
     144            0 :                                 &hv_info->current[i]);
     145              :       }
     146              :    }
     147              : 
     148              :    /* else read only single channel */
     149            0 :    if (!(hv_info->driver[channel]->flags & DF_MULTITHREAD)) {
     150            0 :       status = device_driver(hv_info->driver[channel], CMD_GET,
     151            0 :                                  channel - hv_info->channel_offset[channel],
     152            0 :                                  &hv_info->measured[channel]);
     153            0 :       status = device_driver(hv_info->driver[channel], CMD_GET_CURRENT,
     154            0 :                                  channel - hv_info->channel_offset[channel],
     155            0 :                                  &hv_info->current[channel]);
     156              :    }
     157              : 
     158              :    /* check how much channels have changed since last ODB update */
     159            0 :    act_time = ss_millitime();
     160              : 
     161              :    /* check for update measured */
     162            0 :    max_diff = 0.f;
     163            0 :    min_time = 10000;
     164            0 :    changed = FALSE;
     165            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     166            0 :       if (abs(hv_info->measured[i] - hv_info->measured_mirror[i]) > max_diff)
     167            0 :          max_diff = abs(hv_info->measured[i] - hv_info->measured_mirror[i]);
     168              : 
     169              :       /* indicate change if variation more than the threshold */
     170            0 :       if (abs(hv_info->measured[i] - hv_info->measured_mirror[i]) >
     171            0 :           hv_info->update_threshold[i] && hv_info->measured[i] > 10)
     172            0 :          changed = TRUE;
     173              : 
     174            0 :       if (act_time - hv_info->last_change[i] < min_time)
     175            0 :          min_time = act_time - hv_info->last_change[i];
     176              :    }
     177              : 
     178              :    /* update if change is more than update_sensitivity or less than 5sec ago
     179              :       or last update is older than a minute */
     180            0 :    if (changed || (min_time < 5000 && max_diff > 0) ||
     181            0 :        act_time - hv_info->last_update > 60000) {
     182            0 :       hv_info->last_update = act_time;
     183              : 
     184            0 :       for (i = 0; i < hv_info->num_channels; i++)
     185            0 :          hv_info->measured_mirror[i] = hv_info->measured[i];
     186              : 
     187            0 :       db_set_data(hDB, hv_info->hKeyMeasured, hv_info->measured,
     188            0 :                   sizeof(float) * hv_info->num_channels, hv_info->num_channels,
     189              :                   TID_FLOAT);
     190              : 
     191            0 :       pequipment->odb_out++;
     192              :    }
     193              : 
     194              :    /* check for update current */
     195            0 :    max_diff = 0.f;
     196            0 :    min_time = 10000;
     197            0 :    changed = FALSE;
     198            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     199            0 :       if (abs(hv_info->current[i] - hv_info->current_mirror[i]) > max_diff)
     200            0 :          max_diff = abs(hv_info->current[i] - hv_info->current_mirror[i]);
     201              : 
     202            0 :       if (abs(hv_info->current[i] - hv_info->current_mirror[i]) >
     203            0 :           hv_info->update_threshold_current[i])
     204            0 :          changed = TRUE;
     205              : 
     206            0 :       if (act_time - hv_info->last_change[i] < min_time)
     207            0 :          min_time = act_time - hv_info->last_change[i];
     208              :    }
     209              : 
     210              :    /* update if change is more than update_sensitivity or less than 5sec ago */
     211            0 :    if (changed || (min_time < 5000 && max_diff > 0)) {
     212            0 :       for (i = 0; i < hv_info->num_channels; i++)
     213            0 :          hv_info->current_mirror[i] = hv_info->current[i];
     214              : 
     215            0 :       db_set_data(hDB, hv_info->hKeyCurrent, hv_info->current,
     216            0 :                   sizeof(float) * hv_info->num_channels, hv_info->num_channels,
     217              :                   TID_FLOAT);
     218              : 
     219            0 :       pequipment->odb_out++;
     220              :    }
     221              : 
     222            0 :    return status;
     223              : }
     224              : 
     225              : /*------------------------------------------------------------------*/
     226              : 
     227            0 : INT ivc32_ramp(HV_INFO * hv_info)
     228              : {
     229            0 :    INT i, status = 0, switch_tag = FALSE;
     230            0 :    float delta, ramp_speed = 0;
     231              : 
     232            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     233            0 :       if (hv_info->demand[i] != hv_info->demand_mirror[i]) {
     234              :          /* check if to ramp up or down */
     235            0 :          if ((hv_info->demand[i] >= 0.f) && (hv_info->demand_mirror[i] > 0.f)) {
     236            0 :             switch_tag = FALSE;
     237            0 :             if (hv_info->demand[i] > hv_info->demand_mirror[i])
     238            0 :                ramp_speed = hv_info->ramp_step[i];
     239              :             else
     240            0 :                ramp_speed = hv_info->step_time[i];
     241              :          }
     242            0 :          if ((hv_info->demand[i] >= 0.f) && (hv_info->demand_mirror[i] < 0.f)) {
     243            0 :             switch_tag = TRUE;
     244            0 :             ramp_speed = hv_info->step_time[i];
     245              :          }
     246            0 :          if ((hv_info->demand[i] < 0.f) && (hv_info->demand_mirror[i] > 0.f)) {
     247            0 :             switch_tag = TRUE;
     248            0 :             ramp_speed = hv_info->step_time[i];
     249              :          }
     250            0 :          if ((hv_info->demand[i] < 0.f) && (hv_info->demand_mirror[i] < 0.f)) {
     251            0 :             switch_tag = FALSE;
     252            0 :             if (hv_info->demand[i] > hv_info->demand_mirror[i])
     253            0 :                ramp_speed = hv_info->step_time[i];
     254              :             else
     255            0 :                ramp_speed = hv_info->ramp_step[i];
     256              :          }
     257            0 :          if (hv_info->demand_mirror[i] == 0.f) {
     258            0 :             switch_tag = FALSE;
     259            0 :             ramp_speed = hv_info->ramp_step[i];
     260              :          }
     261              : 
     262            0 :          if (ramp_speed == 0.f)
     263            0 :             if (switch_tag)
     264            0 :                hv_info->demand_mirror[i] = 0.f; /* go to zero */
     265              :             else
     266            0 :                hv_info->demand_mirror[i] = hv_info->demand[i];  /* step directly to the new high voltage */
     267              :          else {
     268            0 :             delta = (float) ((ss_millitime() -
     269            0 :                               hv_info->last_change[i]) / 1000.0 * ramp_speed);
     270            0 :             if (hv_info->demand[i] > hv_info->demand_mirror[i])
     271            0 :                hv_info->demand_mirror[i] =
     272            0 :                    MIN(hv_info->demand[i], hv_info->demand_mirror[i] + delta);
     273              :             else
     274            0 :                hv_info->demand_mirror[i] =
     275            0 :                    MAX(hv_info->demand[i], hv_info->demand_mirror[i] - delta);
     276              :          }
     277            0 :          status = device_driver(hv_info->driver[i], CMD_SET,
     278            0 :                                 i - hv_info->channel_offset[i], hv_info->demand_mirror[i]);
     279            0 :          hv_info->last_change[i] = ss_millitime();
     280              :       }
     281              :    }
     282              : 
     283            0 :    return status;
     284              : }
     285              : 
     286              : 
     287              : /*------------------------------------------------------------------*/
     288              : 
     289            0 : void ivc32_demand(INT hDB, INT hKey, void *info)
     290              : {
     291              :    INT i;
     292              :    HV_INFO *hv_info;
     293              :    EQUIPMENT *pequipment;
     294              : 
     295            0 :    pequipment = (EQUIPMENT *) info;
     296            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     297              : 
     298              :    /* check for voltage limit */
     299            0 :    for (i = 0; i < hv_info->num_channels; i++)
     300            0 :       if (hv_info->demand[i] > hv_info->voltage_limit[i])
     301            0 :          hv_info->demand[i] = hv_info->voltage_limit[i];
     302              : 
     303              :    /* set individual channels only if demand value differs */
     304            0 :    for (i = 0; i < hv_info->num_channels; i++)
     305            0 :       if (hv_info->demand[i] != hv_info->demand_mirror[i])
     306            0 :          hv_info->last_change[i] = ss_millitime();
     307              : 
     308            0 :    pequipment->odb_in++;
     309              : 
     310            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     311              :       /* if device can do hardware ramping, just set value */
     312            0 :       if (hv_info->driver[i]->flags & DF_HW_RAMP) {
     313            0 :          if (hv_info->demand[i] != hv_info->demand_mirror[i]) {
     314            0 :             device_driver(hv_info->driver[i], CMD_SET,
     315            0 :                           i - hv_info->channel_offset[i], hv_info->demand[i]);
     316            0 :             hv_info->last_change[i] = ss_millitime();
     317            0 :             hv_info->demand_mirror[i] = hv_info->demand[i];
     318              :          }
     319              :       }
     320              :    }
     321            0 : }
     322              : 
     323              : /*------------------------------------------------------------------*/
     324              : // in WORD
     325            0 : void ivc32_set_trip_time(INT hDB, INT hKey, void *info)
     326              : {
     327              :    INT i;
     328              :    HV_INFO *hv_info;
     329              :    EQUIPMENT *pequipment;
     330              : 
     331            0 :    pequipment = (EQUIPMENT *) info;
     332            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     333              : 
     334              :    /* check for voltage limit */
     335            0 :    for (i = 0; i < hv_info->num_channels; i++)
     336            0 :       device_driver(hv_info->driver[i], CMD_SET_TRIP_TIME,
     337            0 :                     i - hv_info->channel_offset[i], hv_info->trip_time[i]);
     338              : 
     339            0 :    pequipment->odb_in++;
     340            0 : }
     341              : 
     342              : /*------------------------------------------------------------------*/
     343              : 
     344            0 : void ivc32_set_current_limit(INT hDB, INT hKey, void *info)
     345              : {
     346              :    INT i;
     347              :    HV_INFO *hv_info;
     348              :    EQUIPMENT *pequipment;
     349              : 
     350            0 :    pequipment = (EQUIPMENT *) info;
     351            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     352              : 
     353              :    /* check for voltage limit */
     354            0 :    for (i = 0; i < hv_info->num_channels; i++)
     355            0 :       device_driver(hv_info->driver[i], CMD_SET_CURRENT_LIMIT,
     356            0 :                     i - hv_info->channel_offset[i], hv_info->current_limit[i]);
     357              : 
     358            0 :    pequipment->odb_in++;
     359            0 : }
     360              : 
     361              : /*------------------------------------------------------------------*/
     362              : // Actually Ramp step in WORD
     363            0 : void ivc32_set_rampstep(INT hDB, INT hKey, void *info)
     364              : {
     365              :    INT i;
     366              :    HV_INFO *hv_info;
     367              :    EQUIPMENT *pequipment;
     368              : 
     369            0 :    pequipment = (EQUIPMENT *) info;
     370            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     371              : 
     372              :    /* check for voltage limit */
     373            0 :    for (i = 0; i < hv_info->num_channels; i++)
     374            0 :       device_driver(hv_info->driver[i], CMD_SET_RAMPUP,
     375            0 :                     i - hv_info->channel_offset[i], hv_info->ramp_step[i]);
     376              : 
     377            0 :    pequipment->odb_in++;
     378            0 : }
     379              : 
     380              : /*------------------------------------------------------------------*/
     381              : // Actually Step Time in WORD
     382            0 : void ivc32_set_steptime(INT hDB, INT hKey, void *info)
     383              : {
     384              :    INT i;
     385              :    HV_INFO *hv_info;
     386              :    EQUIPMENT *pequipment;
     387              : 
     388            0 :    pequipment = (EQUIPMENT *) info;
     389            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     390              : 
     391              :    /* check for voltage limit */
     392            0 :    for (i = 0; i < hv_info->num_channels; i++)
     393            0 :       device_driver(hv_info->driver[i], CMD_SET_RAMPDOWN,
     394            0 :                     i - hv_info->channel_offset[i], hv_info->step_time[i]);
     395              : 
     396            0 :    pequipment->odb_in++;
     397            0 : }
     398              : 
     399              : /*------------------------------------------------------------------*/
     400              : // Not implemented for IVC32 use as software limit
     401            0 : void ivc32_set_voltage_limit(INT hDB, INT hKey, void *info)
     402              : {
     403              :    //HV_INFO *hv_info;
     404              :    //EQUIPMENT *pequipment;
     405              : 
     406              :    //pequipment = (EQUIPMENT *) info;
     407              :    //hv_info = (HV_INFO *) pequipment->cd_info;
     408              : 
     409              :    // voltage_limit has been updated by open_record
     410              :    
     411              :    /* check for voltage limit */
     412              :    //for (i = 0; i < hv_info->num_channels; i++)
     413              :    //   device_driver(hv_info->driver[i], CMD_SET_VOLTAGE_LIMIT,
     414              :    //                 i - hv_info->channel_offset[i], hv_info->voltage_limit[i]);
     415              : 
     416              :    //pequipment->odb_in++;
     417            0 : }
     418              : 
     419              : /*------------------------------------------------------------------*/
     420              : 
     421            0 : void ivc32_update_label(INT hDB, INT hKey, void *info)
     422              : {
     423              :    INT i, status;
     424              :    HV_INFO *hv_info;
     425              :    EQUIPMENT *pequipment;
     426              : 
     427            0 :    pequipment = (EQUIPMENT *) info;
     428            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     429              : 
     430              :    /* update channel labels based on the midas channel names */
     431            0 :    for (i = 0; i < hv_info->num_channels; i++)
     432            0 :       status = device_driver(hv_info->driver[i], CMD_SET_LABEL,
     433            0 :                              i - hv_info->channel_offset[i],
     434            0 :                              hv_info->names + NAME_LENGTH * i);
     435              : 
     436              :    (void)status; // defeat "set but unused" warning
     437            0 : }
     438              : 
     439              : /*------------------------------------------------------------------*/
     440              : 
     441            0 : void validate_odb_array(HNDLE hDB, HV_INFO *hv_info, const char *path, double default_value, int cmd,
     442              :                         float *array, void (*callback)(INT,INT,void *) ,EQUIPMENT *pequipment)
     443              : {
     444              :    int i;
     445              :    HNDLE hKey;
     446              : 
     447            0 :    for (i = 0; i < hv_info->num_channels; i++)
     448            0 :       array[i] = (float)default_value;
     449            0 :    if (db_find_key(hDB, hv_info->hKeyRoot, path, &hKey) != DB_SUCCESS)
     450            0 :       for (i = 0; i < hv_info->num_channels; i++)
     451            0 :          device_driver(hv_info->driver[i], cmd,
     452            0 :                        i - hv_info->channel_offset[i], array + i);
     453            0 :    db_merge_data(hDB, hv_info->hKeyRoot, path, array, sizeof(float) * hv_info->num_channels,
     454              :                  hv_info->num_channels, TID_FLOAT);
     455            0 :    db_find_key(hDB, hv_info->hKeyRoot, path, &hKey);
     456            0 :    assert(hKey);
     457            0 :    db_open_record(hDB, hKey, array, sizeof(float) * hv_info->num_channels, MODE_READ,
     458              :                   callback, pequipment);
     459            0 : }
     460              : 
     461              : /*------------------------------------------------------------------*/
     462              : 
     463            0 : INT ivc32_init(EQUIPMENT * pequipment)
     464              : {
     465              :    int status, size, i, j, index, offset;
     466              :    char str[256];
     467              :    HNDLE hDB, hKey;
     468              :    HV_INFO *hv_info;
     469              : 
     470              :    /* allocate private data */
     471            0 :    pequipment->cd_info = calloc(1, sizeof(HV_INFO));
     472            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     473              : 
     474              :    /* get class driver root key */
     475            0 :    cm_get_experiment_database(&hDB, NULL);
     476            0 :    sprintf(str, "/Equipment/%s", pequipment->name);
     477            0 :    db_create_key(hDB, 0, str, TID_KEY);
     478            0 :    db_find_key(hDB, 0, str, &hv_info->hKeyRoot);
     479              : 
     480              :    /* save event format */
     481            0 :    size = sizeof(str);
     482            0 :    db_get_value(hDB, hv_info->hKeyRoot, "Common/Format", str, &size, TID_STRING, TRUE);
     483              : 
     484            0 :    if (equal_ustring(str, "Fixed"))
     485            0 :       hv_info->format = FORMAT_FIXED;
     486            0 :    else if (equal_ustring(str, "MIDAS"))
     487            0 :       hv_info->format = FORMAT_MIDAS;
     488              :    else
     489            0 :       assert(!"unknown ODB Common/Format");
     490              : 
     491              :    /* count total number of channels */
     492            0 :    for (i = 0, hv_info->num_channels = 0; pequipment->driver[i].name[0]; i++) {
     493            0 :       if (pequipment->driver[i].channels == 0) {
     494            0 :          cm_msg(MERROR, "hv_init", "Driver with zero channels not allowed");
     495            0 :          return FE_ERR_ODB;
     496              :       }
     497              : 
     498            0 :       hv_info->num_channels += pequipment->driver[i].channels;
     499              :    }
     500              : 
     501            0 :    if (hv_info->num_channels == 0) {
     502            0 :       cm_msg(MERROR, "hv_init", "No channels found in device driver list");
     503            0 :       return FE_ERR_ODB;
     504              :    }
     505              : 
     506              :    /* Allocate memory for buffers */
     507            0 :    hv_info->names = (char *) calloc(hv_info->num_channels, NAME_LENGTH);
     508              : 
     509            0 :    hv_info->demand = (float *) calloc(hv_info->num_channels, sizeof(float));
     510            0 :    hv_info->measured = (float *) calloc(hv_info->num_channels, sizeof(float));
     511            0 :    hv_info->current = (float *) calloc(hv_info->num_channels, sizeof(float));
     512              : 
     513            0 :    hv_info->update_threshold = (float *) calloc(hv_info->num_channels, sizeof(float));
     514            0 :    hv_info->update_threshold_current = (float *) calloc(hv_info->num_channels, sizeof(float));
     515            0 :    hv_info->voltage_limit = (float *) calloc(hv_info->num_channels, sizeof(float));
     516            0 :    hv_info->current_limit = (float *) calloc(hv_info->num_channels, sizeof(float));
     517            0 :    hv_info->ramp_step = (float *) calloc(hv_info->num_channels, sizeof(float));
     518            0 :    hv_info->step_time = (float *) calloc(hv_info->num_channels, sizeof(float));
     519            0 :    hv_info->trip_time = (float *) calloc(hv_info->num_channels, sizeof(float));
     520              : 
     521            0 :    hv_info->demand_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
     522            0 :    hv_info->measured_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
     523            0 :    hv_info->current_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
     524            0 :    hv_info->last_change = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
     525              : 
     526            0 :    hv_info->dd_info = (void**) calloc(hv_info->num_channels, sizeof(void *));
     527            0 :    hv_info->channel_offset = (INT *) calloc(hv_info->num_channels, sizeof(INT));
     528            0 :    hv_info->driver = (DEVICE_DRIVER**) calloc(hv_info->num_channels, sizeof(void *));
     529              : 
     530            0 :    if (!hv_info->driver) {
     531            0 :       cm_msg(MERROR, "hv_init", "Not enough memory");
     532            0 :       return FE_ERR_ODB;
     533              :    }
     534              : 
     535              :    /*---- Initialize device drivers ----*/
     536              : 
     537              :    /* call init method */
     538            0 :    for (i = 0; pequipment->driver[i].name[0]; i++) {
     539            0 :       sprintf(str, "Settings/Devices/%s", pequipment->driver[i].name);
     540            0 :       status = db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
     541            0 :       if (status != DB_SUCCESS) {
     542            0 :          db_create_key(hDB, hv_info->hKeyRoot, str, TID_KEY);
     543            0 :          status = db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
     544            0 :          if (status != DB_SUCCESS) {
     545            0 :             cm_msg(MERROR, "hv_init", "Cannot create %s entry in online database", str);
     546            0 :             free_mem(hv_info);
     547            0 :             return FE_ERR_ODB;
     548              :          }
     549              :       }
     550              : 
     551            0 :       status = device_driver(&pequipment->driver[i], CMD_INIT, hKey);
     552            0 :       if (status != FE_SUCCESS) {
     553            0 :          free_mem(hv_info);
     554            0 :          return status;
     555              :       }
     556              :    }
     557              : 
     558              :    /* compose device driver channel assignment */
     559            0 :    for (i = 0, j = 0, index = 0, offset = 0; i < hv_info->num_channels; i++, j++) {
     560            0 :       while (j >= pequipment->driver[index].channels && pequipment->driver[index].name[0]) {
     561            0 :          offset += j;
     562            0 :          index++;
     563            0 :          j = 0;
     564              :       }
     565              : 
     566            0 :       hv_info->driver[i] = &pequipment->driver[index];
     567            0 :       hv_info->channel_offset[i] = offset;
     568              :    }
     569              : 
     570              :    /*---- Create/Read settings ----*/
     571              :    /* Names */
     572            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     573            0 :       if ((i>=0) && (i<8))   sprintf(hv_info->names + NAME_LENGTH * i, "Front%%CH %d", i);
     574            0 :       if ((i>=8) && (i<16))  sprintf(hv_info->names + NAME_LENGTH * i, "Back%%CH %d", i);
     575            0 :       if ((i>=16) && (i<24)) sprintf(hv_info->names + NAME_LENGTH * i, "Left%%CH %d", i);
     576            0 :       if ((i>=24) && (i<32)) sprintf(hv_info->names + NAME_LENGTH * i, "Right%%CH %d", i);
     577              :    }
     578            0 :    if (db_find_key(hDB, hv_info->hKeyRoot, "Settings/Names", &hKey) != DB_SUCCESS)
     579            0 :       for (i = 0; i < hv_info->num_channels; i++)
     580            0 :          device_driver(hv_info->driver[i], CMD_GET_LABEL,
     581            0 :                        i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
     582            0 :    db_merge_data(hDB, hv_info->hKeyRoot, "Settings/Names",
     583            0 :                  hv_info->names, NAME_LENGTH * hv_info->num_channels,
     584              :                  hv_info->num_channels, TID_STRING);
     585            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Settings/Names", &hKey);
     586            0 :    assert(hKey);
     587            0 :    db_open_record(hDB, hKey, hv_info->names, NAME_LENGTH * hv_info->num_channels,
     588              :                   MODE_READ, ivc32_update_label, pequipment);
     589              : 
     590              :    /* Update threshold */
     591            0 :    validate_odb_array(hDB, hv_info, "Settings/Update Threshold Measured", 0.5, CMD_GET_THRESHOLD,
     592              :                       hv_info->update_threshold, NULL, NULL);
     593              : 
     594              :    /* Update threshold current */
     595            0 :    validate_odb_array(hDB, hv_info, "Settings/Update Threshold Current", 0.5, CMD_GET_THRESHOLD_CURRENT,
     596              :                       hv_info->update_threshold_current, NULL, NULL);
     597              : 
     598              :    /* Voltage limit */
     599            0 :    validate_odb_array(hDB, hv_info, "Settings/Voltage Limit", 100, CMD_GET_VOLTAGE_LIMIT,
     600              :                       hv_info->voltage_limit, ivc32_set_voltage_limit, pequipment);
     601              :    /* Current limit */
     602            0 :    validate_odb_array(hDB, hv_info, "Settings/Current Limit", 50, CMD_GET_CURRENT_LIMIT,
     603              :                       hv_info->current_limit, ivc32_set_current_limit, pequipment);
     604              : 
     605              :    /* Trip Time */
     606            0 :    validate_odb_array(hDB, hv_info, "Settings/Trip Time", 1000, CMD_GET_TRIP_TIME,
     607              :                       hv_info->trip_time, ivc32_set_trip_time, pequipment);
     608              : 
     609              :    /* Ramp Step */
     610            0 :    validate_odb_array(hDB, hv_info, "Settings/Ramp Step", 5, CMD_GET_RAMPUP,
     611              :                       hv_info->ramp_step, ivc32_set_rampstep, pequipment);
     612              : 
     613              :    /* Step Time */
     614            0 :    validate_odb_array(hDB, hv_info, "Settings/Step Time", 50, CMD_GET_RAMPDOWN,
     615              :                       hv_info->step_time, ivc32_set_steptime, pequipment);
     616              : 
     617              :    /*---- Create/Read variables ----*/
     618              : 
     619              :    /* Demand */
     620            0 :    db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Demand",
     621            0 :                  hv_info->demand, sizeof(float) * hv_info->num_channels,
     622              :                  hv_info->num_channels, TID_FLOAT);
     623            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Variables/Demand", &hv_info->hKeyDemand);
     624              : 
     625              :    /* Measured */
     626            0 :    db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Measured",
     627            0 :                  hv_info->measured, sizeof(float) * hv_info->num_channels,
     628              :                  hv_info->num_channels, TID_FLOAT);
     629            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Variables/Measured", &hv_info->hKeyMeasured);
     630            0 :    memcpy(hv_info->measured_mirror, hv_info->measured,
     631            0 :           hv_info->num_channels * sizeof(float));
     632              : 
     633              :    /* Current */
     634            0 :    db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Current",
     635            0 :                  hv_info->current, sizeof(float) * hv_info->num_channels,
     636              :                  hv_info->num_channels, TID_FLOAT);
     637            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Variables/Current", &hv_info->hKeyCurrent);
     638            0 :    memcpy(hv_info->current_mirror, hv_info->current,
     639            0 :           hv_info->num_channels * sizeof(float));
     640              : 
     641              :    /*---- set labels form midas SC names ----*/
     642            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     643            0 :       status = device_driver(hv_info->driver[i], CMD_SET_LABEL,
     644            0 :                              i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
     645              :    }
     646              : 
     647              :    /*---- set/get values ----*/
     648            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     649            0 :       if ((hv_info->driver[i]->flags & DF_PRIO_DEVICE) == 0) {
     650            0 :          hv_info->demand_mirror[i] = MIN(hv_info->demand[i], hv_info->voltage_limit[i]);
     651            0 :          status = device_driver(hv_info->driver[i], CMD_SET,
     652            0 :                                 i - hv_info->channel_offset[i], hv_info->demand_mirror[i]);
     653            0 :          status = device_driver(hv_info->driver[i], CMD_SET_TRIP_TIME,
     654            0 :                                 i - hv_info->channel_offset[i], hv_info->trip_time[i]);
     655            0 :          status = device_driver(hv_info->driver[i], CMD_SET_CURRENT_LIMIT,
     656            0 :                                 i - hv_info->channel_offset[i], hv_info->current_limit[i]);
     657            0 :          status = device_driver(hv_info->driver[i], CMD_SET_VOLTAGE_LIMIT,
     658            0 :                                 i - hv_info->channel_offset[i], hv_info->voltage_limit[i]);
     659            0 :          status = device_driver(hv_info->driver[i], CMD_SET_RAMPUP,
     660            0 :                                 i - hv_info->channel_offset[i], hv_info->ramp_step[i]);
     661            0 :          status = device_driver(hv_info->driver[i], CMD_SET_RAMPDOWN,
     662            0 :                                 i - hv_info->channel_offset[i], hv_info->step_time[i]);
     663              :       } else {
     664            0 :          status = device_driver(hv_info->driver[i], CMD_GET_DEMAND,
     665            0 :                                 i - hv_info->channel_offset[i], hv_info->demand + i);
     666            0 :          hv_info->demand_mirror[i] = hv_info->demand[i];
     667              : 
     668            0 :          status = device_driver(hv_info->driver[i], CMD_GET_CURRENT_LIMIT,
     669            0 :                                 i - hv_info->channel_offset[i], &hv_info->current_limit[i]);
     670            0 :          status = device_driver(hv_info->driver[i], CMD_GET_VOLTAGE_LIMIT,
     671            0 :                                 i - hv_info->channel_offset[i], &hv_info->voltage_limit[i]);
     672            0 :          status = device_driver(hv_info->driver[i], CMD_GET_RAMPUP,
     673            0 :                                 i - hv_info->channel_offset[i], &hv_info->ramp_step[i]);
     674            0 :          status = device_driver(hv_info->driver[i], CMD_GET_RAMPDOWN,
     675            0 :                                 i - hv_info->channel_offset[i], &hv_info->step_time[i]);
     676            0 :          status = device_driver(hv_info->driver[i], CMD_GET_TRIP_TIME,
     677            0 :                                 i - hv_info->channel_offset[i], &hv_info->trip_time[i]);
     678              :       }
     679              :    }
     680            0 :    db_set_record(hDB, hv_info->hKeyDemand, hv_info->demand,
     681            0 :                  hv_info->num_channels * sizeof(float), 0);
     682              : 
     683              :    /*--- open hotlink to HV demand values ----*/
     684            0 :    db_open_record(hDB, hv_info->hKeyDemand, hv_info->demand,
     685            0 :                   hv_info->num_channels * sizeof(float), MODE_READ, ivc32_demand,
     686              :                   pequipment);
     687              : 
     688              :    /* initially read all channels */
     689            0 :    for (i=0 ; i<hv_info->num_channels ; i++) {
     690              : 
     691            0 :       hv_info->driver[i]->dd(CMD_GET, hv_info->driver[i]->dd_info,
     692            0 :                              i - hv_info->channel_offset[i], &hv_info->measured[i]);
     693            0 :       hv_info->driver[i]->dd(CMD_GET_CURRENT, hv_info->driver[i]->dd_info,
     694            0 :                              i - hv_info->channel_offset[i], &hv_info->current[i]);
     695              : 
     696            0 :       hv_info->measured_mirror[i] = hv_info->measured[i];
     697            0 :       hv_info->current_mirror[i]  = hv_info->current[i];
     698              :    }
     699            0 :    db_set_data(hDB, hv_info->hKeyCurrent, hv_info->current,
     700            0 :                sizeof(float) * hv_info->num_channels, hv_info->num_channels,
     701              :                TID_FLOAT);
     702            0 :    pequipment->odb_out++;
     703              : 
     704            0 :    return FE_SUCCESS;
     705              : }
     706              : 
     707              : /*------------------------------------------------------------------*/
     708              : 
     709            0 : INT ivc32_exit(EQUIPMENT * pequipment)
     710              : {
     711              :    INT i;
     712              : 
     713            0 :    free_mem((HV_INFO *) pequipment->cd_info);
     714              : 
     715              :    /* call exit method of device drivers */
     716            0 :    for (i = 0; pequipment->driver[i].dd != NULL; i++)
     717            0 :       device_driver(&pequipment->driver[i], CMD_EXIT);
     718              : 
     719            0 :    return FE_SUCCESS;
     720              : }
     721              : 
     722              : /*------------------------------------------------------------------*/
     723              : 
     724            0 : INT ivc32_idle(EQUIPMENT * pequipment)
     725              : {
     726              :    INT act, status;
     727              :    DWORD act_time;
     728              :    HV_INFO *hv_info;
     729              : 
     730            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     731              : 
     732              :    /* do ramping */
     733              : //   ivc32_ramp(hv_info);
     734              : 
     735              :    /* select next measurement channel */
     736            0 :    hv_info->last_channel = (hv_info->last_channel + 1) % hv_info->num_channels;
     737              : 
     738              :    /* measure channel */
     739            0 :    status = ivc32_read(pequipment, hv_info->last_channel);
     740              : 
     741              :    /* additionally read channel recently updated if not multithreaded */
     742            0 :    if (!(hv_info->driver[hv_info->last_channel]->flags & DF_MULTITHREAD)) {
     743              : 
     744            0 :       act_time = ss_millitime();
     745              : 
     746            0 :       act = (hv_info->last_channel_updated + 1) % hv_info->num_channels;
     747            0 :       while (!(act_time - hv_info->last_change[act] < 10000)) {
     748            0 :          act = (act + 1) % hv_info->num_channels;
     749            0 :          if (act == hv_info->last_channel_updated) {
     750              :             /* non found, so return */
     751            0 :             return status;
     752              :          }
     753              :       }
     754              : 
     755              :       /* updated channel found, so read it additionally */
     756            0 :       status = ivc32_read(pequipment, act);
     757            0 :       hv_info->last_channel_updated = act;
     758              :    }
     759              : 
     760            0 :    return status;
     761              : }
     762              : 
     763              : /*------------------------------------------------------------------*/
     764              : 
     765            0 : INT cd_ivc32_read(char *pevent, int offset)
     766              : {
     767              :    float *pdata;
     768              :    HV_INFO *hv_info;
     769              :    EQUIPMENT *pequipment;
     770              : 
     771            0 :    pequipment = *((EQUIPMENT **) pevent);
     772            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     773              : 
     774            0 :    if (hv_info->format == FORMAT_FIXED) {
     775            0 :       memcpy(pevent, hv_info->demand, sizeof(float) * hv_info->num_channels);
     776            0 :       pevent += sizeof(float) * hv_info->num_channels;
     777              : 
     778            0 :       memcpy(pevent, hv_info->measured, sizeof(float) * hv_info->num_channels);
     779            0 :       pevent += sizeof(float) * hv_info->num_channels;
     780              : 
     781            0 :       memcpy(pevent, hv_info->current, sizeof(float) * hv_info->num_channels);
     782            0 :       pevent += sizeof(float) * hv_info->num_channels;
     783              : 
     784            0 :       return 3 * sizeof(float) * hv_info->num_channels;
     785            0 :    } else if (hv_info->format == FORMAT_MIDAS) {
     786            0 :       bk_init(pevent);
     787              : 
     788              :       /* create DMND bank */
     789            0 :       bk_create(pevent, "DMND", TID_FLOAT, (void**) &pdata);
     790            0 :       memcpy(pdata, hv_info->demand, sizeof(float) * hv_info->num_channels);
     791            0 :       pdata += hv_info->num_channels;
     792            0 :       bk_close(pevent, pdata);
     793              : 
     794              :       /* create MSRD bank */
     795            0 :       bk_create(pevent, "MSRD", TID_FLOAT, (void**) &pdata);
     796            0 :       memcpy(pdata, hv_info->measured, sizeof(float) * hv_info->num_channels);
     797            0 :       pdata += hv_info->num_channels;
     798            0 :       bk_close(pevent, pdata);
     799              : 
     800              :       /* create CRNT bank */
     801            0 :       bk_create(pevent, "CRNT", TID_FLOAT, (void**) &pdata);
     802            0 :       memcpy(pdata, hv_info->current, sizeof(float) * hv_info->num_channels);
     803            0 :       pdata += hv_info->num_channels;
     804            0 :       bk_close(pevent, pdata);
     805              : 
     806            0 :       return bk_size(pevent);
     807              :    } else {
     808            0 :       assert(!"unknown hv_info->format");
     809              :       return 0;
     810              :    }
     811              : }
     812              : 
     813              : /*------------------------------------------------------------------*/
     814              : 
     815            0 : INT cd_ivc32(INT cmd, PEQUIPMENT pequipment)
     816              : {
     817              :    INT status;
     818              : 
     819            0 :    switch (cmd) {
     820            0 :    case CMD_INIT:
     821            0 :       status = ivc32_init(pequipment);
     822            0 :       break;
     823              : 
     824            0 :    case CMD_EXIT:
     825            0 :       status = ivc32_exit(pequipment);
     826            0 :       break;
     827              : 
     828            0 :    case CMD_START:
     829            0 :       status = ivc32_start(pequipment);
     830            0 :       break;
     831              : 
     832            0 :    case CMD_STOP:
     833            0 :       status = ivc32_stop(pequipment);
     834            0 :       break;
     835              : 
     836            0 :    case CMD_IDLE:
     837            0 :       status = ivc32_idle(pequipment);
     838            0 :       break;
     839              : 
     840            0 :    default:
     841            0 :       cm_msg(MERROR, "HV class driver", "Received unknown command %d", cmd);
     842            0 :       status = FE_ERR_DRIVER;
     843            0 :       break;
     844              :    }
     845              : 
     846            0 :    return status;
     847              : }
        

Generated by: LCOV version 2.0-1